Skip to content
OTFotf
All posts

SaaS kit: keep Issues board as owned five-column Kanban, not a ghost board

D
DaveAuthor
8 min read
SaaS kit: keep Issues board as owned five-column Kanban, not a ghost board

The SaaS Dashboard kit ships an Issues board you can open on the live demo today: five status columns, drag cards between them, and the same issue rows show up in backlog and tasks views. That board only helps a production team if a card move updates one owned issue row — not a ghost board that lives in component state while your agent invents a second tracker beside the schema.

This post is that status write-path invariant. It is not the click-through product tour — that lives at /blog/saas-kit-live-tour. It is not Stripe Customer Portal for plan changes — that shipped earlier today at /blog/saas-kit-stripe-customer-portal. It is not analytics charts you own — that is /blog/how-to-build-an-analytics-dashboard-with-ai. It is not the Retool/Appsmith compare — that decision map is /blog/otf-vs-retool-appsmith-dashboard. And it is not the broader admin-panel assembly order — that is /blog/how-to-build-an-admin-panel-with-ai.

What the kit already names for issues

OTF lists the SaaS Dashboard kit on https://otf-kit.dev/templates/saas-dashboard and documents screens, tables, and deploy on https://otf-kit.dev/docs/templates/saas-dashboard. Standalone price is $99; the kit is also in the Everything Bundle on https://otf-kit.dev/pricing. Live proof before buy sits at https://saas.otf-kit.dev.

Kit docs name the issue surfaces explicitly:

  • Issues board: /home/issues-board — Kanban with five status columns
  • Issues backlog: /home/issues-backlog — drag-orderable backlog grouped by priority
  • Tasks: /home/tasks — all issues as a record table plus an issue-detail sheet
  • Projects: /home/projects and /home/projects/:id — list plus a project detail that includes team and tasks
  • App tables that own the domain: issue, label, issueLabel, comment, attachment (alongside workspace, team, teamMember, project, notification, savedView, and related auth tables)
  • Seed: bun run db:seed loads a deterministic 4-user / 5-project / 50-issue dataset
  • Agent handoff: CLAUDE.md, .cursorrules, and 20+ tested prompts under ai/prompts/ — including bounded jobs such as add a CRUD entity and add a screen
  • Deploy: bash scripts/deploy-railway.sh

That is the product spine. The marketing page also lists issue tracking and a Kanban board among the shipped dashboard features. The kit does not claim a hosted Linear clone or a third-party project tool as a module. For the default loop, the invariant is simpler: a card on the board must be the same issue row backlog and tasks already read — never a parallel board store an agent invents after checkout.

Why ghost boards fail teams (and agents)

Three failure modes show up the week after you buy:

  1. Board-only status — drag updates local column state, refresh restores the seed status, and teammates see a different column than the person who moved the card.
  2. Parallel tracker invent — an agent prompted with "add a Kanban" creates a second cards table beside issue, then backlog, tasks, and project detail diverge.
  3. Backlog and board as two products — priority order on /home/issues-backlog writes one place while board columns write another, so "what's next" and "what's in progress" disagree.

The public Kanban component docs on https://otf-kit.dev/docs/components/ui/advanced show the UI contract: five columns, drag-reorder, and an onCardMove(cardId, toCol, toIndex) callback. That callback is where honesty lives. If move only mutates component state, you shipped a demo. If move updates the owned issue status (and optional rank) the other screens already query, you shipped a product.

Board, backlog, and tasks converge on one issue row

Board, backlog, and tasks share one owned issue — not a parallel cards table.

11 production screens. Login, database, payments — all wired.

The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.

See the live demo

The owned status contract: board, backlog, and tasks share one row

Treat the Issues board as a view over issue, not a separate product:

  1. Identity — every card id is an issue id. Do not allocate a second card identity on drop.
  2. Status — the five columns map to the issue status field the table and seed already understand. Kit docs describe the board as five status columns; the public Kanban component example uses Backlog, To do, In progress, Review, and Done as the five-column shape — keep one enum in schema, not five hard-coded strings copied into three screens.
  3. MoveonCardMove persists status (and column index if you store rank). Idempotent: a second drop to the same column updates or no-ops; it never inserts a twin issue.
  4. Backlog seam/home/issues-backlog reorders by priority on the same rows. Priority changes do not invent a backlog-only entity.
  5. Tasks seam/home/tasks lists the same issues in a record table and opens the same detail sheet. Filters by project, status, and priority (as the live product page states for issue tracking) must hit the same columns the board writes.
  6. Project seam — project detail shows team + tasks for that project; those tasks are still issue rows scoped by project, not a third store.

Illustrative shape (labeled sketch — not a private kit file dump):

// Illustrative board move — YOUR-PRODUCTION-DOMAIN API
type IssueStatus = "backlog" | "todo" | "doing" | "review" | "done";

async function onCardMove(
  issueId: string,
  toStatus: IssueStatus,
  toIndex: number
) {
  // Idempotent update on issue id — never INSERT a second row for a drag
  await api.patch(`/issues/${issueId}`, {
    status: toStatus,
    boardIndex: toIndex,
  });
  // Invalidate board + backlog + tasks queries that share this entity
}

Keep labels and comments on label / issueLabel / comment. When an agent wants a "simple tags array on the card," point it back at the join tables the seed already uses. Parallel tag strings are how filters and saved views rot.

Keep ai/prompts as the extension path, not a second board

After clone, migrate, and seed (documented on the SaaS kit docs page), open Cursor or Claude Code on the buyer repo. Prefer a bounded prompt over "rebuild issue tracking":

Read CLAUDE.md and ai/prompts/.
1) Keep board, backlog, and tasks on the issue table — do not invent a second tracker
2) Card move must PATCH status (and rank) by issue id — never double-insert
3) New fields use add-CRUD-entity / add-screen recipes (schema → route → hook → screen → sidebar)
4) Labels stay on label + issueLabel; comments stay on comment
5) Do not replace the five-column board with a third-party project SaaS embed
6) Prefer the existing /home/issues-board path over a parallel /kanban route

That prompt works because the kit already names the hard seams. You are extending a SaaS product, not interviewing the model about project-management information architecture. Preview the shipped board on https://saas.otf-kit.dev before you buy if you have not opened the demo login yet.

When you need a new entity beside issues (for example a customer request object that still lands on the board), use the add-CRUD-entity recipe: generate migration, add the server route under the kit's router conventions, copy a query hook with optimistic updates, wrap a screen, register the route, add the sidebar item. Do not paste a new board library next to the Kanban already documented in the component docs.

Dragging a Kanban card persists status on the issue row

onCardMove must persist status so refresh cannot resurrect the old column.

How to verify the invariant before you call it shipped

Run the checks a release engineer would run on day two:

CheckPass signal
Seed loadbun run db:seed yields ~50 issues across projects
Board moveDrag a card; refresh; column matches the persisted status
Backlog syncSame issue's priority order survives reload
Tasks syncRecord table and detail sheet show the same status as the board
Agent restraintA "add Kanban" prompt does not create a second cards table
Deploy pathbash scripts/deploy-railway.sh still deploys your clone, not a canvas

If any row fails, fix the write path before you theme the columns. Pretty boards with dishonest status are worse than a plain table that tells the truth.

How this fits the rest of OTF without confusing the SKU

SaaS Dashboard is the web product lane — auth, billing, dashboard KPIs, issues, analytics, projects, teams, settings — not a $9 landing template and not Fitness or Booking. Landing templates remain the marketing-site lane. Fitness-kit remains the wellness product lane. Booking-kit remains the appointment product lane. Full-stack kits remain the $99 product lane when you need auth, data, payments, and a deployable app wired together.

If you need the live click-through before purchase, read /blog/saas-kit-live-tour. If you need self-serve plan changes after Checkout, read /blog/saas-kit-stripe-customer-portal. If you need analytics ownership, read /blog/how-to-build-an-analytics-dashboard-with-ai. If you still need the internal-tools versus product-repo decision, read /blog/otf-vs-retool-appsmith-dashboard once. If you need the wider admin assembly order (roles → tables → audit), read /blog/how-to-build-an-admin-panel-with-ai.

When the issue loop matches — five-column board, priority backlog, tasks table, owned issue rows, agent recipes that extend instead of regenerate — start on https://otf-kit.dev/templates/saas-dashboard, open the live demo, and buy when the screen set matches. Keep Issues board as owned Kanban. Leave ghost boards and parallel trackers on the scrap heap.

Sources

SaaS Dashboard kit product page: https://otf-kit.dev/templates/saas-dashboard

SaaS Dashboard kit docs (screens, tables, seed, deploy): https://otf-kit.dev/docs/templates/saas-dashboard

Live SaaS demo: https://saas.otf-kit.dev

Kanban component docs (five-column board + onCardMove): https://otf-kit.dev/docs/components/ui/advanced

Pricing: https://otf-kit.dev/pricing

Templates catalog: https://otf-kit.dev/templates

Related: SaaS kit live tour — https://otf-kit.dev/blog/saas-kit-live-tour

Related: SaaS kit Stripe Customer Portal — https://otf-kit.dev/blog/saas-kit-stripe-customer-portal

Related: How to build an analytics dashboard with AI — https://otf-kit.dev/blog/how-to-build-an-analytics-dashboard-with-ai

Related: OTF vs Retool / Appsmith — https://otf-kit.dev/blog/otf-vs-retool-appsmith-dashboard

Related: How to build an admin panel with AI — https://otf-kit.dev/blog/how-to-build-an-admin-panel-with-ai

kitstemplatesarchitecture
OTF SaaS Dashboard Kit

Ship the product, not the setup.

  • 11 production screens — auth, billing, team, analytics, settings
  • Real database, payments, and login — all wired on day 1
  • AI configs pre-tuned so your agent extends instead of regenerates