How the suite works
Every workflow in A. S. Toler Software is a series of state changes across panels. This page maps each one in pictures — who does what, where it happens, and how data moves from a bid invitation to a paid invoice. If anything on a panel feels unclear, check the flow below.
The mirror of the billing flow above — this is the A/P side. From sub award through executed contract, monthly pay app, and unconditional lien release.
flowchart LR
A[Sub awarded scope
CM/PM Panel] --> B[Upload draft
subcontract PDF]
B --> C[Claude AI review
risk + flags + recommendation]
C --> D{Need redline?}
D -->|Yes| E[PM redlines
upload redlined]
D -->|No| F[Upload executed PDF
status: awarded]
E --> F
F --> G[Invite sub to portal
magic link email]
G --> H[Sub signs in via
Google OAuth]
H --> I[Sub submits Pay App
Sub Portal
amount + period + lien release]
I --> J[Accounting reviews
status: approved]
J --> K[Check cut
status: paid]
K --> L[Unconditional release
received on file]
L --> M[Next pay cycle unlocked]
M --> I
classDef pm fill:#fef3e8,stroke:#b45a32,color:#2a2722
classDef ai fill:#f3e8f7,stroke:#7a2eb4,color:#2a2722
classDef sub fill:#fff7e6,stroke:#c89020,color:#2a2722
classDef acct fill:#e8f0fe,stroke:#1e6cb4,color:#2a2722
classDef done fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
class A,B,E,F pm
class C ai
class G,H,I sub
class J,K acct
class L,M done
Color key: orange = PM actions · purple = AI · gold = sub actions · blue = Accounting · green = completed. Each pay app entry writes to sub_pay_apps_cloud; comments go in sub_pay_app_comments_cloud.
From the sub's perspective in /subcontractor/ — three tabs (Jobs, Compliance, Profile) covering everything a sub needs to do business with A. S. Toler. Compliance tab shows a numeric badge when items are expiring; Profile is read-only (email billing@ for changes).
flowchart LR
A[Sub gets invite email
magic link] --> B[Clicks link & signs in
Google OAuth]
B --> C{Authorized
contact?}
C -->|No| Z[Locked out:
'Contact A. S. Toler']
C -->|Yes| D[3-tab Portal:
Jobs · Compliance · Profile]
D --> E[Jobs tab
KPIs + Avg days invoice→paid
Contracts + Pay Apps]
D --> F[Compliance tab
CSLB · DIR · WC · GL · W-9
tab badge when expiring]
D --> G[Profile tab
Legal name · DBA · Contacts
CSI div · License #s · read-only]
E --> H[+ Submit New Pay App]
H --> I[Pick project + period + amount]
I --> J[Status: submitted
Accounting reviews]
J --> K[Status: approved
Check cut: paid]
classDef neutral fill:#f0ecdf,stroke:#8a8479,color:#2a2722
classDef good fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
classDef bad fill:#f5e8e8,stroke:#b43232,color:#2a2722
classDef accent fill:#fef3e8,stroke:#b45a32,color:#2a2722
class A,B,C,D,E,F,G neutral
class H,I,J accent
class K good
class Z bad
How a prospect lands in our pipeline, what happens automatically, and where to work them.
flowchart LR
A[Prospect visits
tolercorp.com] --> B[Clicks "Start a conversation"]
B --> C[/start/ inquiry form
name · email · project · budget · timeline · scope/]
C --> D{Honeypot &
email validation}
D -->|fail| X[Marked spam
no emails sent]
D -->|pass| E[Insert into
leads_cloud
status: new]
E --> F[Email Alex
at alex.toler@tolercorp.com]
E --> G[Auto-ack to prospect
"reply within 1 business day"]
F --> H[Bid Panel → Leads]
H --> I{Pipeline status}
I --> I1[new]
I1 --> I2[contacted]
I2 --> I3[qualifying]
I3 --> I4[proposing]
I4 --> I5[proposed]
I5 --> I6[won/lost]
I6 -->|won| J[Promote to firms_cloud +
contacts_cloud +
bids_cloud or projects_cloud]
Where leads come from. The landing-page hero CTA "Start a conversation" now routes to /start/ instead of mailto. The form collects name, email, phone, company, role, project type, location, budget range, timeline, and a free-text scope. Mailto fallbacks remain in the Contact section for direct outreach.
What happens automatically. On submit: (1) honeypot + email-format checks run, (2) the row is inserted into leads_cloud, (3) a notification email goes to Alex with the inquiry detail (with the prospect’s email set as Reply-To so replying just works), (4) an auto-ack is sent to the prospect from alex.toler@tolercorp.com. All emails are best-effort — insert always succeeds even if SMTP fails.
Where to work them. Open Bid Panel → Leads (or visit /leads/ directly). The view shows pipeline counts at the top, a searchable/filterable table, and a click-to-expand drawer per lead. The drawer lets you change status, add internal notes, and set a next-action with date. Status “spam” is hidden by default. Click any rollup card to filter to that status; the “All” card shows everything except spam.
When a lead converts. Mark status won and (when productized) promote into the CRM: a new firms_cloud row, a contacts_cloud row for the inquiry person, and either a bids_cloud row (if it’s entering the bid pipeline) or a projects_cloud row (if it’s going straight to engagement). The promoted_firm_id, promoted_contact_id, converted_to_bid_est, and converted_to_project_est columns on the lead capture the linkage.
The full arc of every job at A. S. Toler — from inbound invitation through warranty period. Each phase shows the actor, the panel they work in, and the documents born in that step.
flowchart TB
subgraph P0["PHASE 0–1 · Lead & Setup"]
direction LR
L1[Inbound ITB / SBX listing] --> L2[+ New Bid
Bid Panel]
L2 --> L3[EST# YY-NNN assigned
Storage prefix + Gmail label]
end
subgraph P2["PHASE 2–4 · Estimate & Award"]
direction LR
E1[AI Takeoff +
Sub solicitation] --> E2[Bid sent
status: SENT]
E2 --> E3{Outcome}
E3 -->|Awarded| E4[JOB# AST-YY-NNN
status: AWARDED]
E3 -->|Lost| EX[Archived for analytics]
end
subgraph P5["PHASE 5 · Promotion to Project"]
direction LR
PR1[Sign prime contract
CM/PM Panel] --> PR2[Customer portal
account created]
PR2 --> PR3[Contract PDF uploaded
Customer can download]
end
subgraph P6["PHASE 6 · Pre-Construction"]
direction LR
C1[SOV created
line-by-line by CSI div] --> C2[Subcontracts awarded
+ AI review]
C2 --> C3[Submittals seeded
permits + COIs in]
end
subgraph P7["PHASE 7 · Construction"]
direction TB
F1[Field: daily reports
photos · time · receipts]
F2[CM/PM: RFIs · submittals
punchlist · COs / PCOs]
F3[Sub bills A.S. Toler
+ lien release]
F4[Pay App → Invoice
G702/G703 PDF]
F4 --> F5[Customer portal
Approve / Reject / Comment]
F5 --> F6[Payment received]
F6 --> F7[Sub disbursement
+ unconditional release]
F7 --> F3
end
subgraph P89["PHASES 8–9 · Closeout & Archive"]
direction LR
Z1[Substantial completion
cert + punchlist signed] --> Z2[Final invoice + retention
release + warranty letter]
Z2 --> Z3[NOC filed with county]
Z3 --> Z4[jobs_archive_cloud
profit % · lessons]
end
L3 --> E1
E4 --> PR1
PR3 --> C1
C3 --> F1
F1 --> F4
F2 --> F4
F7 --> Z1
classDef phase0 fill:#f0ecdf,stroke:#8a8479,color:#2a2722
classDef phase2 fill:#fef3e8,stroke:#b45a32,color:#2a2722
classDef phase5 fill:#e8f0fe,stroke:#1e6cb4,color:#2a2722
classDef phase6 fill:#fff7e6,stroke:#c89020,color:#2a2722
classDef phase7 fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
classDef phase8 fill:#f3e8f7,stroke:#7a2eb4,color:#2a2722
classDef done fill:#dcf5e3,stroke:#1e7a3a,color:#2a2722,font-weight:bold
classDef gone fill:#f5e8e8,stroke:#b43232,color:#2a2722
class L1,L2,L3 phase0
class E1,E2,E3,E4 phase2
class EX gone
class PR1,PR2,PR3 phase5
class C1,C2,C3 phase6
class F1,F2,F3,F4,F5,F6,F7 phase7
class Z1,Z2,Z3 phase8
class Z4 done
The cash chain (Phase 7): SOV → Pay App (CM/PM) → Invoice (Accounting "Send") → Customer Portal (Approve) → Paid → Sub disbursement → Unconditional release on file → next cycle unlocks.
Color key: beige = lead · orange = estimating · blue = contract signing · gold = pre-con · green = construction · purple = closeout · dark green = archived.
From SOV at contract sign through paid invoice. Industry-standard, matches AIA G702/G703 pattern.
flowchart LR
A[Contract signed] --> B[PM creates SOV
in CM/PM Panel]
B --> C{Monthly walk
~25th of month}
C --> D[PM enters % complete
per SOV line
Pay App = draft]
D --> E[PM hits 'Send to
Accounting']
E --> F[Accounting reviews
math + COs
Pay App = submitted]
F -->|Looks good| G[Accounting generates
G702 PDF + emails
Pay App = sent]
F -->|Needs fix| D
G --> H[Customer opens
portal invoice]
H --> I{Customer
action}
I -->|Approve| J[Invoice = approved
Awaiting payment]
I -->|Reject + comment| D
I -->|Comment / question| F
J --> K[Payment received]
K --> L[Accounting marks paid
Pay App = paid]
L --> M[Sub disbursement
+ lien releases]
classDef pm fill:#fef3e8,stroke:#b45a32,color:#2a2722
classDef acct fill:#e8f0fe,stroke:#1e6cb4,color:#2a2722
classDef cust fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
classDef contract fill:#f0ecdf,stroke:#8a8479,color:#2a2722
class A,M contract
class B,C,D,E pm
class F,G,L,K acct
class H,I,J cust
Color key: beige = contract milestones · orange = PM actions ·
blue = Accounting actions · green = Customer actions. Every state change is recorded
in invoice_actions_cloud (audit trail).
From an inbound ITB landing in alex.toler@'s Gmail through awarded job that becomes the basis for billing above.
flowchart LR
A[Inbound ITB / RFP / RFQ
email arrives] --> B[Bid Radar:
Claude classifies]
B -->|Real invitation| C[Lands on Bid Panel
'Suggested Bids' tab]
B -->|Vendor reply / OOS| X[Filtered out]
C --> D[Estimator clicks
'Set up bid']
D --> E[EST# assigned
e.g. 26-047
Gmail label + storage
prefix created]
E --> F[Estimator solicits
subs via Sub Solicitation
tab]
F --> G[Sub bids come in
tracked per CSI div]
G --> H[Estimator builds
final bid amount]
H --> I[Bid sent to GC/owner
before due date]
I --> J{Outcome}
J -->|Awarded| K[JOB-YY-NN assigned
Project becomes active
in CM/PM Panel]
J -->|Not awarded| L[Archived in Bid Panel
kept for win-rate analytics]
K --> M[Billing flow begins
see above]
classDef inbox fill:#f0ecdf,stroke:#8a8479,color:#2a2722
classDef est fill:#fef3e8,stroke:#b45a32,color:#2a2722
classDef sub fill:#fff7e6,stroke:#c89020,color:#2a2722
classDef done fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
classDef gone fill:#f5e8e8,stroke:#b43232,color:#2a2722
class A,B inbox
class C,D,E,H,I est
class F,G sub
class K,M done
class X,L gone
From the client's perspective in /customer/ — no jargon, no internal IDs, just their projects + invoices.
flowchart LR
A[Client signs in with
Google: client@theirco.com] --> B{Authorized
contact?}
B -->|Yes| C[Dashboard:
Outstanding $ · Billed YTD · Paid YTD]
B -->|No| Z[Locked out:
'Contact billing@tolercorp.com']
C --> D[Active Projects card
per project: contract,
billed, balance, % billed]
C --> E[Outstanding Invoices
per invoice: status pill,
balance, View/Download/Approve]
C --> F[Recently Paid
last 5 paid invoices]
E --> G{Click
invoice}
G -->|View PDF| H[G702-style PDF
opens in new tab]
G -->|Download| I[Saves INV-NNNN.pdf]
G -->|Approve| J[Status: approved
Accounting notified]
G -->|Reject / Comment| K[Comment thread
visible to A. S. Toler staff]
classDef neutral fill:#f0ecdf,stroke:#8a8479,color:#2a2722
classDef good fill:#e8f7ee,stroke:#1e7a3a,color:#2a2722
classDef bad fill:#f5e8e8,stroke:#b43232,color:#2a2722
classDef accent fill:#fef3e8,stroke:#b45a32,color:#2a2722
class A,B,C,D,E,F neutral
class H,I,J good
class Z bad
class G,K accent
Slice 1: link your inbox once; the ASTC label tree gets provisioned and stays there. No reading or auto-routing yet.
How to link. Open Email Panel, click Link Inbox, complete the Google consent screen as your @tolercorp.com address. We create 16 labels under ASTC - Business/. Existing messages and other labels are not touched — additive only.
The 16-label tree.
What's NOT in slice 1. No inbox reading. No auto-classification. No filters. No outbound sending from this panel. Slice 2 adds auto-triage (Claude assigns labels based on subject + sender) — requires expanding OAuth scopes to gmail.modify + gmail.readonly. The connection card has an Expand scopes button stubbed until that lands.
Disconnect anytime. The Disconnect button revokes our refresh token at Google. The labels themselves stay in your Gmail (you can delete them manually if you re-organize). Re-linking re-provisions the tree idempotently — no duplicate labels.
How the LinkedIn dashboard works and what the once a week cadence looks like.
What happens automatically. Every Monday at 7am Pacific, a scheduled function reads the past week of activity from leads_cloud and bids_cloud and asks Claude for five LinkedIn posts in the firm voice. Drafts land in linkedin_drafts_cloud and surface on the LinkedIn panel. The editorial theme rotates each week across five categories: practice philosophy, sector commentary, market observation, operational craft, and public opportunity watch.
What you do. Open the LinkedIn panel. Pick the strongest one or two drafts. Click Copy, paste into LinkedIn's native composer at linkedin.com/company/astoler-corp/admin/, hit the clock icon to schedule a publish time later that week. Come back to the panel and click Mark Posted. Drop a LinkedIn URL in the modal if you want the Posted tab to link directly to the live post.
What we never do. Auto post. LinkedIn aggressively bans pages that publish through the API or scraping for a sub 100 employee firm. The native scheduler is the legitimate publish path. Treat this as a Claude assist for the writing, with a human commit on every press of the publish button.
Generate on demand. The Monday cron is the default cadence, but the Generate New Batch button on the panel fires the same function any time. It takes about thirty seconds and costs roughly two cents in Claude tokens per run.
Roadmap. Slice 1 (live now) covers Drafts and Posted. Slice 2 adds a Network log for manual follow and connection tracking. Slice 3 adds a Targets queue where Claude proposes weekly outreach candidates. Slice 4 adds Insights via screenshot OCR of LinkedIn analytics.
Identifying NorCal general contractors whose owners are likely aging toward retirement, then driving slow relationship-led outreach.
What it is. An internal workbench for spotting acquisition candidates in the NorCal trades (Bay Area · Sacramento · Redding triangle). The goal is 5 to 15 hand picked prospects per month for relationship outreach over 24 months, surfacing one to three actual acquisition conversations. It is deliberately not a volume tool.
What you run weekly. CSLB's data portal is an interactive ASP.NET form — there is no static download URL we can call from a cron. So the CSLB ingest is a local CLI on your laptop: node scripts/yard-ingest-cslb.js. It walks the form via Playwright, downloads the Master / Personnel / WC files, filters to NorCal class B contractors, scores each license on license tenure plus personnel size plus bond plus other signals, and refreshes the Yard panel. Schedule it via Windows Task Scheduler for a Sunday morning run.
What you do. Open Yard, sort by score, click a prospect. The detail page shows the CSLB signal, the transparent factor breakdown (each weight times value), and a Workspace card where you confirm the owner name and write a one sentence specific reason this prospect stood out. Without that reason, the v1 drafting flow refuses to draft.
What we never do. Auto send. Bulk outreach. Generic templates. Mention acquisition or sale or valuation on a first touch. The voice is a career contractor asking to learn from someone who built a successful GC business, not a private equity buyer or broker.
Local CLIs. All three ingest jobs run from your laptop, not the cloud, because every source requires a real browser walk (CSLB form, SoS SPA) or huge static files (county shapefiles): node scripts/yard-ingest-cslb.js (weekly), node scripts/yard-ingest-sos.js --top 25 (after each ingest, on the highest-scored prospects), node scripts/yard-ingest-counties.js --county alameda --file ./data/alameda_parcels.csv (quarterly per county).
Roadmap. v0.5 (live now) ships the visible workbench: scored prospects · detail page · manual touchpoint logging. v1 adds Gmail integration (Yard label tree · Sent watcher · inbound auto draft as a Gmail Draft, never auto sent · keyword guard on words like price, sale, NDA, broker), the persona aware drafting flow, and the dashboard (funnel · response rate · cadence health).
Who does what, where. Single-operator firms (A. S. Toler today) wear all hats — the surfaces still matter because each role is a different mental mode.
| Role | What they do | Where they work |
|---|---|---|
| Estimator | Read incoming ITBs, solicit subs, send bids, manage CRM (Firms · Contacts · Touchpoints) | Bid Panel (/bid-panel/) |
| CM / PM (Construction / Project Manager) | Run awarded jobs: SOV, pay apps, subcontracts (w/ AI review), change orders, submittals, RFIs, schedule, POs, permits, punch list, lien releases, closeout, daily reports, live Job Costing | CM/PM Panel (/pm-panel/) |
| Field Super / Foreman | Crew time, receipts, daily reports from jobsite | Field Panel (/field-panel/) |
| Accounting | Send invoices to clients, mark paid, AR aging, sub disbursement, POs, receipts, 1099s | Accounting Panel (/accounting/) |
| Principal | Cross-project rollup: backlog health, margin, owner concentration | Ops Panel (/ops-panel/) |
| Safety Manager (or PM wearing the hat) | Toolbox talks, incident reports, JHA library, OSHA 300 log feed | Safety Panel (/safety/) |
| Admin / Owner | Invite teammates, system reference, activity log, compliance, deploys | Admin Panel (/admin/) — alex.toler@ only |
| Client | View invoices/COs by project, approve/reject, comment, download contract | Customer Portal (/customer/) |
| Subcontractor | View contracts, submit pay apps, see compliance status, upload lien releases | Subcontractor Portal (/subcontractor/) |
Construction-finance terms that appear throughout the suite.
YY-NNN. Lives forever in Bid Panel even if not awarded.JOB-YY-NN. The customer-facing project identifier.
Spot a flow that's missing or wrong? Update site/help/index.html — diagrams are Mermaid, easy to edit.