The studio and the problem
Studio Yona is a seven-person residential architecture studio in Los Angeles. Its projects go through City of Los Angeles and LA County plan check. So on top of the design work, every job carries a submittal path, a set of departmental clearances and a corrections cycle. Tasks lived in Asana and files in Dropbox, and invoicing was halfway through a move from Illustrator to QuickBooks.
The Asana account looked busy but had no structure. At migration it held 88 active projects and 2,487 tasks. Every one of the 88 projects had exactly one section, named "Untitled section".
Only the studio's three template projects had real sections. They held 40 tasks for City of Los Angeles work, 21 for other California jurisdictions and 42 for Ventura and LA County. When we first read the account, the studio had applied them to none of its 70 numbered projects. Each project was a flat list of tasks, with the project's street name as a prefix so people could tell them apart in My Tasks.
The numbers in our notes were wrong, too. Earlier notes said 82 projects and 1,532 tasks, and the first full read of the account came back with the same figures. The cause was a pagination trap. Asana's next-page object carries a path without the API prefix, and following it returns the web app's HTML instead of JSON. So every project over 100 tasks quietly came back as exactly 100, and the whole thing looked like a rate limit.
Four projects were hiding 626 tasks between them. We caught them on migration day, because a second count, by assignee, disagreed with the per-project count.
Of the 2,487 tasks, 2,256 (91 percent) were already complete, 95 percent carried a due date and 253 had notes. The whole workspace held one email address and four phone numbers, and no client, fee or invoice data at all. Project numbering had drifted too: two different jobs were both numbered 2634, and two more were both 2643.
The six decisions that shaped the build
Six decisions came out of the first two recorded calls (July 21 and August 11, 2026). Each one changed the shape of everything built after it.
Every project gets its own board, small ones included. A board lets subitems sit under each task, which the corrections workflow needs, and the principal watched a project board being created on a call. The alternative, one Tasks board for the whole studio, failed on arithmetic. At 49 to 64 template tasks per project across 200 projects, that's 10,000 to 13,000 rows on one board.
The property owner is not the client. On a residential job, the client is often a contractor working for the property owner, and the contractor signs the contract. The structure tracks both parties separately instead of guessing which is which.
Fee phases are independent of design phases. The studio's real contract had five work stages and three payments, each triggered by an event. The payments were 20 percent at execution and 50 percent at submittal to Building and Safety. The last 30 percent came at ready to issue. A system that assumed one invoice per design phase would have been wrong on the first job it touched.
Employees must not see what each job is worth. monday.com Pro sets permissions per board, not per column, so this became a structural rule rather than a setting. Every dollar figure lives on private boards and nowhere else.
Nothing in Asana is ever deleted. The migration runs first as a pilot of a handful of projects for the principal's approval, then as the full transfer. The source stays intact afterward.
Documents are PDFs. The studio's contracts and proposals had to come out as files it could send, in its own format and with its own clauses. That ruled out monday docs.
What was built
Overview and intake
A Projects Overview board is the hub, with one row per project. Each row carries the studio's YYNN project number, stage, design phase, jurisdiction, lead PM, client, next action and what the project is waiting on. The design phases are Pre-Design, Schematic, Design Development, Plan Check/CD, Construction Admin and Closeout.
Six views carry the daily work: Active Projects, Pipeline (pre-contract), In Design, Plan Check / Permits, By Stage and a Financials view for the principal only. An internal intake form creates a project. A client-facing inquiry form, with reCAPTCHA and the studio's logo, sends new inquiries to the pipeline.
A numbering service assigns the next number for the year and adopts a number already typed into the project's name. It refuses to reissue a number that already exists, which is the guard Asana never had. It has 25 unit tests. On its first pass over the migrated projects, it reported the two duplicates and rewrote nothing.
The project template and one-click project boards
A 99-task project template in 14 groups holds the studio's own task names, taken word for word from its Asana templates. The design phases come first as numbered groups, and Construction Administration and Closeout come last. In between sits a submittal block for each jurisdiction. The City of Los Angeles block covers planning and the Building and Safety submittal, then clearances. The LA County and Santa Clarita block covers HOA, planning and permit submittals, while other California work has its own block.
A Spawn Project Template button on the overview duplicates the template and deletes the jurisdiction groups that do not apply. It then files the new board in the year's folder and links it back to the overview row. New boards start with 54 tasks for City of Los Angeles jobs, 64 for LA County and 49 for the rest of California.
Task status includes N/A, because a quarter of the studio's tasks are marked "if applicable". Without a way to dismiss them, those tasks sit incomplete forever, which is part of why its 40-task Asana templates went unused. Gantt and calendar views come with every new project board, grouped by phase and colored by status, with a today line and a legend. An Info Hub tab on each board shows the address, parcel number, zone and jurisdiction, mirrored from the overview row so they're typed once.
Fees and billing by phase
A private Contracts board holds one row per project's fee agreement: contract total, retainer, number of fee phases and fee type. A private Payments board holds one row per invoice. Each invoice's subitems are its line items (Fee, Reimbursable, Additional Service, Discount), which map one to one onto QuickBooks line items.
Invoices go out on net-14 terms, numbered in the studio's own convention: the project number plus a six-digit sequence. A Generate Invoice Schedule action builds the retainer and phase invoices from the contract. A Recalculate Total button sums the lines: a $1,000 invoice with an $800 fee line and a $100 discount recalculated to $700.
On the shared overview, contract total, retainer, total fee and paid to date appear only as mirror columns. Those show blank to anyone outside the private boards. Connected columns show project and invoice names, never amounts.
The push that sends invoices to QuickBooks is built and deployed. It uses OAuth with rotating refresh tokens stored on a private tokens board, matches or creates the customer and sends line items on net 14. The monday.com invoice number becomes the QuickBooks DocNumber, and paid status comes back every five minutes. It carries 23 unit tests against the studio's real invoice figures. monday.com has no native QuickBooks integration, so this is custom code hosted on monday.com's own app platform.
Documents
Generate Contract and Generate Proposal buttons on the Contracts board produce the studio's own PDF and file it on the same row. Each button sets a status. A small hosted service checks for that change every three seconds, with a backup check every minute, and does the work.
The contract reproduces all 18 clauses of the studio's General Contract for Services word for word, with its payment prose, exclusions and signature blocks. We proved it by rebuilding the studio's real $9,000 job. The three invoices of $1,800, $4,500 and $2,700 matched the real contract and the real invoice numbers exactly.
Clearances and submissions
In the City of Los Angeles, a permit sits on top of three to twelve smaller departmental approvals. The city issues a Clearance Summary Worksheet at the first round of plan check corrections. The template carries a clearance group per jurisdiction, with one heading per agency.
An Import Clearances button reads the worksheet PDF and creates one subitem per clearance under the right agency. It parsed 6 of 6 clearances on a real City of Los Angeles worksheet and 5 of 5 on a Santa Clarita report. Pressing it twice creates no duplicates. It also refuses a worksheet in another jurisdiction's format, rather than filing county clearances under city headings and calling it a success. A waiting-on column says whether the ball is with the studio or the city.
A rollup computed in the service, not in an automation, flips an agency heading to Blocked the moment any line under it goes to Corrections. A Clearance Library board holds 127 clearances across 25 agencies as reference.
Separately, a Submissions board tracks each submittal by agency (Building and Safety, Planning, BOE, Zoning, Fire, Grading, Fuel Mod, HOA, Building Dept, Other). Each one moves through Awaiting, Received, Corrections, Resubmitted, Approved, RTI, Follow Up and Closed. After seven days of silence, an automation creates a follow-up task on the linked project's board, assigned to the submission's owner. It's a real task, not a notification nobody reads.
The master calendar
A Master Task Rollup board gathers every dated task from every project board. Each row has an Open task link and a Project Home link. The board feeds one Master Calendar and one All Assigned Tasks view, both filtered by person. It's a synced copy rather than a mirror, because a calendar view needs a real date column on the board it sits on.
The service reconciles a sixth of the boards every minute, so every board is checked every six minutes. It carries guards learned the hard way. It never deletes a row younger than 60 minutes, and it deletes at most 200 rows in a pass. It also refuses to delete rows under a board name that two boards share. It has 54 unit tests.
A payroll export produces a CSV of person, project, month and hours from the time-tracking column on every board.
Dashboard and permissions
One private executive dashboard has seven widgets. Three show Projects by Stage, by Health and by Design Phase. The other four show Total Contracted, Collected to Date, Invoiced to Date and Invoices by Status. Dashboard number widgets sum mirror columns, so portfolio totals live on the dashboard rather than in a board's footer.
Notifications go to the person who can act on them. Submission alerts go to the submission's owner. Project health and slippage alerts go to the lead PM, and money alerts go to the principal. A sandbox workspace gives staff somewhere to practice. It's separate from the live workspace, so it cannot show a fee or link to a real contract.
The client database
Asana held no clients at all. The principal compiled a sheet from every signed contract in Dropbox: 128 project rows and 76 unique clients. It loaded as 21 companies and 61 contacts, and 64 of 77 projects now name their client.
The load matched on address, not folder number. The Dropbox folder numbers predated a renumbering in Asana, so matching on number would have put six clients on the wrong project. For thirteen projects with no contract on file, we left the client blank rather than guess.
The migration
The migration ran on August 24, 2026, read-only against Asana through the logged-in browser session. No personal access token was created, so none needed revoking afterward. We deleted the demo data first, because the export proved a demo project carried the wrong number.
A pilot of 9 boards and 229 tasks reconciled 9 of 9 and went to the principal for review. The two projects numbered 2634 migrated as they were, so the duplicate stayed visible instead of hidden.
The full run moved 77 numbered projects and 2,109 tasks, reconciled one to one against the source with zero mismatches. It also moved 103 office rows into a Studio Ops board and 162 tasks onto a 3D rendering board, for 2,374 tasks in total. Sixty archived projects holding 1,668 tasks stayed in Asana on purpose. So did the three template projects, a test project and two buckets of tasks reassigned from people who had left.
Because the source had no sections, each board was made by copying only the template's structure. In a scripted run, that's the only way to carry Gantt and calendar views, which come from the template or get added by hand rather than through the API. Each board's 14 empty groups were replaced with one Project Tasks group. Completed tasks became Done and the rest Not Started.
With 95 percent of tasks carrying a due date, the Gantt filled with real dates for the first time. Three assignees had no monday.com seat, so 268 tasks arrived unassigned, with the original assignee's name kept in Notes.
Afterward, we deleted 23 boards whose every task was complete (389 tasks), leaving 54 live project boards. Their overview rows stayed, because the numbering service reads them. The Asana to monday.com migration page has the full method, including the pagination trap and the automation changes that had to happen before the run.
Verification and handover
The system is checked by a script, not by eye. The command node migration/verify.js runs 42 live checks against the account and stops with an error if any check fails. It checks every board, column, label, folder and count the service depends on, plus whether the Master Task Rollup matches the project boards. It also enforces a ceiling on how many rows the rollup is allowed to create or delete in an hour.
The service is a Node/Express app hosted on monday code, monday.com's own app hosting. Since the handover on September 14, 2026, it runs under the principal's own API token. Every row it writes is attributed to the studio rather than to a consultant, and the studio owns the whole system outright. The studio also has the sandbox copy of its workspace for staff to experiment in.
Timeline: core boards built July 17, first recorded call July 21, second call August 11, migration August 24 and handover September 14. Fifty-nine days.
The numbers
| Item | Figure |
|---|---|
| Asana projects active at migration | 88 |
| Asana tasks at migration | 2,487 |
| Tasks already complete | 2,256 (91%) |
| Tasks carrying a due date | 95% |
| Projects migrated | 77 |
| Project tasks migrated, reconciled with zero mismatches | 2,109 |
| Office rows and 3D rendering tasks migrated | 103 and 162 |
| Archived projects left in Asana | 60 (1,668 tasks) |
| Live project boards after cleanup | 54 |
| Template tasks and groups | 99 in 14 |
| Tasks on a new project board (City of LA, LA County, other CA) | 54, 64, 49 |
| Contract clauses reproduced verbatim | 18 |
| Clearances in the library, agencies | 127, 25 |
| Companies and contacts loaded | 21 and 61 |
| Live verifier checks | 42 |
| Unit tests: numbering, rollup, QuickBooks | 25, 54, 23 |
| Core boards to handover | 59 days |
What is not done, and what to watch
A case study that lists only wins is a brochure. The items below were open at handover.
QuickBooks. The push is built, tested and deployed. Connecting the studio's live QuickBooks company is the final step, and it was still open at handover. Until then, invoices are raised in monday.com and entered in QuickBooks by hand.
Parcel numbers and zoning. They're empty on every project, because they exist in no source: not in Asana and not in the contract sheet. The Info Hub gives them a home, and a person types them once per project.
Google Calendar. It was promised at the first consult and never requested again, so we left it out. monday.com has a native Google Calendar integration if the studio wants it.
Template size. The studio chose to keep all 99 tasks rather than prune the template to the 19-task median its real projects showed. The adoption risk to watch is whether staff use the new project boards. The studio's own 40-task Asana templates had been applied to none of its 70 numbered projects when we first read the account.
Two status colors. Two labels on the clearance status column show the wrong color. monday.com pins a label's color to its id, and the column already carried data. It's cosmetic, documented on the column itself and fixable by hand in the monday.com interface.
Dropbox. Linked, not synced. Each project carries links to its design folder and its billing folder, and creating the folders is still a manual step.
Seats. Three people who held tasks in Asana have no monday.com seat, so 268 tasks sit unassigned with the original assignee's name in Notes. Seats are the principal's call.
What a similar studio pays today
This build went beyond the Full System package. The document generator, the clearance importer, the QuickBooks push and the master calendar are custom app work. A similar studio starting today buys Full System, which starts at $7,000, takes two weeks and includes the move off Asana. It covers design phases, fee and billing by phase, the CA log, consultant coordination, the proposal pipeline, client approvals, permissions and dashboards.
A fixed quote covers the build and any custom app work, such as generated contracts, a clearance importer or a QuickBooks push. The free review sets that number before we build anything.
Add monday.com Pro seats. Pro is $19 per seat per month billed annually, as shown on monday.com/pricing on October 7, 2026. For seven seats, that's $1,596 a year. After the build, the care plan covers ongoing changes: $600 a month for 4 hours or $1,100 a month for 8.
The whole engagement started with a recorded call. If your studio's Asana looks like this one did, book the free 30-minute review and bring your project list as it is today.