Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - blank-space-gsu/TaskTrail · GitHub
Skip to content

Repository files navigation

TaskTrail — a cloud-deployed task coordination platform for teams

Live Web App · Live API · Flutter Mobile Repo · Docs

Architecture · Product flow · Cloud delivery · Local development · Documentation


TaskTrail is a role-aware task coordination system built for small teams. Managers create teams, generate join access, assign one-off or recurring work, and monitor execution. Employees join, pick up assigned work, update progress, and complete tasks. Both experiences run against one shared backend — on the web today, and on mobile from a separate Flutter repo using the same API contracts.

What is live

SurfaceWhereWhat runs there
Webtasktrail.siteStatic SPA on Vercel — manager and employee surfaces
APIapi.tasktrail.siteDockerized Node.js + Express on Oracle Cloud Infrastructure
AuthSupabaseEmail + password, real verification email via Resend-backed SMTP
DataSupabase PostgresUsers, teams, memberships, tasks, assignments, recurring rules
CI/CDGitHub Actions → GHCR → OCIBuild, push, SSH deploy, and verify /health on every main push

Architecture

TaskTrail system architecture — one REST API behind Caddy on OCI, with Supabase Auth, Supabase Postgres, and Resend SMTP

The backend is a strict six-layer pipeline — route → controller → Zod validator → service → repository → Postgres — so HTTP concerns, business rules, and SQL stay cleanly separated. Cross-cutting middleware handles auth, role guards, and response envelopes. Both the web SPA and the mobile app speak the same /api/v1 contract.

Product flow

flowchart LR
Team["Manager creates team"] --> Access["Generate join access"]
Access --> Join["User joins the right team"]
Join --> Assign["Assign one-off or recurring work"]
Assign --> Execute["Employee updates and completes tasks"]
Execute --> Oversight["Manager monitors via Dashboard + Worker Tracker"]
Loading

Every surface in the product supports this one operational loop instead of competing with it.

Role surfaces

RoleSurfacesPurpose
ManagerDashboard · Worker Tracker · Tasks · Teams · ProfileAssign, track, manage rosters, and keep visibility
EmployeeTasks · Calendar · Teams · Join Team · ProfileOnboard, execute, report progress

Goals, hours logging, and productivity metrics from earlier iterations were intentionally removed from the promoted flow to keep the product focused.

Cloud delivery

ConcernChoice
Web hostingVercel static deployment
API hostingDedicated OCI VM
Reverse proxyCaddy → api.tasktrail.site → 127.0.0.1:4000
ContainerizationDockerized backend
CI/CDGitHub Actions → GHCR → OCI over SSH
VerificationPost-deploy probe of /api/v1/health
Schema changesManual Supabase migrations by design

The deployment workflow lives in .github/workflows/backend-deploy.yml and the remote restart logic in backend/scripts/deploy-oci-backend.sh.

Repository layout

cloud-computing-project/
├── backend/ # Node.js + Express REST API
│ ├── src/ # routes, controllers, services, repositories, middleware
│ ├── sql/ # schema source files
│ ├── scripts/ # seed, smoke, audit, deploy utilities
│ ├── tests/ # unit + integration tests
│ ├── docs/ # architecture, auth, API, deployment docs
│ └── Dockerfile
├── frontend/ # Plain HTML/CSS/JS SPA (no build step)
├── emails/ # Supabase Auth verification templates
├── docs/assets/ # README visuals
├── .github/workflows/ # CI/CD
└── README.md

Local development

Backend

cd backend
cp .env.example .env
npm install
npm run dev

Useful commands: npm test, npm run smoke:local, npm run seed:demo-group, npm run seed:clean-demo, npm run audit:local.

Frontend

cd frontend
python3 -m http.server 5500

The frontend points at http://localhost:4000/api/v1 in development and https://api.tasktrail.site/api/v1 in production.

Dockerized backend

docker build -t tasktrail-backend ./backend
docker run --rm -p 4000:4000 --env-file backend/.env tasktrail-backend

Demo access

After npm run seed:demo-group:

olivia.hart@tasktrail.local ethan.reyes@tasktrail.local
priya.shah@tasktrail.local nina.patel@tasktrail.local
marcus.lee@tasktrail.local

Password is the value of DEMO_USER_PASSWORD in backend/.env.

Design decisions worth calling out

  • One backend, multiple clients. Web and mobile share the same API contract and role model.
  • Backend-managed auth. Clients never talk directly to Supabase Auth for protected operations.
  • Durable memberships. Leaving and rejoining a team preserves history and keeps roster queries clean.
  • Recurring rules generate real tasks. Generated work behaves like any other task for assignment, updates, and history.
  • Stable response envelope. Every response uses the same { ok, data, error } shape.
  • No web build step. The SPA stays lightweight; the backend carries the real product logic.

Documentation

Backend docs live in backend/docs/:

TopicDoc
Project overviewPROJECT_OVERVIEW.md
ArchitectureBACKEND_ARCHITECTURE.md
Database schemaDATABASE_SCHEMA.md
API referenceAPI_REFERENCE.md
Auth & RBACAUTH_AND_RBAC.md
Frontend integrationFRONTEND_INTEGRATION_GUIDE.md
DeploymentDEPLOYMENT_GUIDE.md
Testing strategyTESTING_STRATEGY.md

Contributor guidance lives in AGENTS.md.

Mobile client

The standalone Flutter client lives at Harry830/tasktrail-mobile. It consumes the same live backend and role model as the web app.

Legacy surfaces

Earlier iterations included hours logging, productivity metrics, and goals. Those backend surfaces remain for compatibility but are no longer part of the promoted product spine or active client experience.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages