Forma
Forma is a multipurpose admin dashboard built with React, TypeScript, Vite and Tailwind CSS. It includes 41 screens and state examples for business dashboards, SaaS analytics, CRM, invoicing, subscriptions, support and project work.
Explore Forma · Open the live demo
This guide covers Forma 0.2.0. The source package also includes setup, customization, module and integration guides in its docs/ folder.
Quick start
Section titled “Quick start”Install and run
Section titled “Install and run”- Download the Forma ZIP from your Lemon Squeezy purchase and extract it.
- Open a terminal in the extracted folder containing
package.json. - Use Node.js 22.12 or newer in the Node 22 line, with npm, and run:
npm cinpm run devOpen the address printed in your terminal, normally http://127.0.0.1:5173. Start at /dashboard for the business overview or /overview for the project workspace.
No API keys or environment file are needed to explore the included demo. The package was verified with Node 22.22.3. Its lockfile records the installed dependency versions.
Build and preview
Section titled “Build and preview”npm run buildnpm run previewThe build checks TypeScript and writes production assets to dist/. Preview serves that build, normally at http://127.0.0.1:4173. Run the app through a server rather than opening index.html directly.
Explore the sample workspace
Section titled “Explore the sample workspace”The first visit loads fictional records. Changes persist in the current browser, including projects, invoices, opportunities, tickets, subscription preferences and saved reports.
Use Demo guide → Reset sample data to restore the original records. This discards local demo edits. Changed fixture files will not replace an existing browser save until you reset it or use a fresh browser profile.
Choose your starting point
Section titled “Choose your starting point”| Application | Start with |
|---|---|
| SaaS product | Product analytics, pricing, billing, authentication and onboarding |
| Client portal or agency tool | Projects, clients, milestones, files, opportunities and invoices |
| Analytics dashboard | Trends, acquisition, conversion funnels, retention, events and saved reports |
| Internal business tool | Business overview, sales pipeline, support, calendar, team and reusable tables |
The sidebar groups screens under Business, Workspace, and Manage & build. Workspace setup lets you choose Studio, SaaS or Client work and your preferred appearance. Every module remains available after setup.
Screens and routes
Section titled “Screens and routes”The 41-screen count includes individual account flows and system-state examples. Parameterized detail routes use your record IDs.
| Area | Routes | Included behavior |
|---|---|---|
| Business overview | /dashboard | Collected invoice revenue, open opportunity value, support counts, current plan and links to related records |
| Workspace overview | /overview | Project totals, status and workload charts, milestone progress and interactive completion timeline |
| Projects | /projects, /projects/:projectId | Grid/list/board views, filters, creation, editing, milestones, comments, file metadata, starring and archiving |
| Tasks | /tasks | Personal/team views, assignment, priorities, dates and completion |
| Clients | /clients, /clients/:clientId | Contact records, notes, projects, opportunities, invoices and support conversations |
| Files and inbox | /files, /inbox | Searchable metadata library, activity, read states and contextual links |
| Team and preferences | /team, /settings | Members, invitation workflows, role labels, profile, workspace preferences, appearance and density |
| Sales pipeline | /pipeline | Editable opportunities, owner filters, drag-and-drop stage changes, accessible stage selects, list view and CSV |
| Invoices | /invoices, /invoices/:invoiceId | Line items, tax and totals, status filters, bulk actions, draft/sent/paid/void states, detail, CSV and printing |
| Plans and billing | /pricing, /billing, /billing/history | Monthly/annual plans, plan changes, cancellation/resume, usage, billing identity and sample receipts |
| Product analytics | /analytics | Date/channel filters, interactive trends, acquisition and accessible chart data |
| Analytics detail | /analytics/funnels, /analytics/retention, /analytics/events, /analytics/reports | Conversion funnel, cohort table, event search/details, saved views and exports |
| Support | /support, /support/:ticketId | New tickets, status/priority/assignee, conversation threads, replies, internal notes and resolution |
| Calendar | /calendar | Month navigation, project filter, milestone dates and links back to work |
| Integrations | /integrations | Catalog search, categories and local connection states |
| Developer tools | /developer | Show-once demo key creation, copy, permission labels and revocation |
| Security | /security, /security/audit | Verification preferences, sample sessions, role guidance and local business activity |
| Account flows | /auth/sign-in, /auth/sign-up, /auth/forgot-password, /auth/verify-email | Validated account forms, recovery preview and verification flow |
| Workspace setup | /onboarding | Workspace/use case, appearance and confirmation steps |
| Interface patterns | /patterns, /patterns/forms, /patterns/tables, /patterns/states | Reusable forms, tables, selection, pagination, validation, empty/loading/error and confirmation examples |
| System states | /status/403, /status/404, /status/maintenance | Application-state designs with recovery links |
How the workflows connect
Section titled “How the workflows connect”Projects, clients and sales
Section titled “Projects, clients and sales”Client relationships use IDs. A client detail page collects its projects, opportunities, invoices and support conversations. Global search finds projects, clients, milestones, business records and application pages.
Project progress comes from its milestones. Completing a project completes its unfinished milestones; reopening work updates the project state. Archived projects stay in the data but leave active collections.
The sales pipeline supports dragging cards between stages. Its stage selects provide the same action for keyboard and touch users. The project board is a separate view that groups projects by status.
Invoices and subscription plans
Section titled “Invoices and subscription plans”Create an invoice, choose a client and add line items. Quantity, unit price and tax determine its total. Currency is stored in integer cents; each line and the tax amount are rounded before totals are displayed.
Draft invoices can be edited, marked sent and later marked paid. Collected revenue on the business dashboard derives from paid invoices. Voided invoices remain in the record. Print / save PDF opens the browser print dialog; Export line items downloads a CSV.
The pricing page demonstrates monthly and annual subscription plans. A confirmed change updates billing and usage limits. Plans with too few seats for the current team show an error. Cancellation and resume controls change the local subscription state.
The subscription prices inside the demo are fictional example plans, separate from the purchase price of the Forma template. Receipt history is sample historical data and does not change when you select another plan.
Analytics and reports
Section titled “Analytics and reports”The analytics module uses a deterministic 90-day sample dataset. Period and channel filters drive the totals, trend chart and funnel. Hover or focus chart points for values, or open the chart’s data table.
Saved reports retain their period, channel and metric. They reopen a view with those filters rather than saving an immutable snapshot. The retention table demonstrates a cohort model; the event explorer uses a separate sample fixture. Connect these views to your analytics service when building your application.
The workspace completion timeline is separate: it can show current milestone completion dates or labeled sample history. Reopening a milestone clears its current completion date; this timeline is not a permanent event log.
Support and account setup
Section titled “Support and account setup”New support tickets open their conversation immediately. Save a reply or internal note, change priority or assignee, and resolve a conversation. Messages stay in the browser until you connect a delivery service.
The account screens demonstrate sign-in, sign-up, recovery and verification. Use 123456 for the demo verification code. Passwords stay in transient component state and are never stored or sent. Onboarding saves workspace and appearance preferences, then opens the selected starting dashboard.
Customize the dashboard
Section titled “Customize the dashboard”Branding, colors and typography
Section titled “Branding, colors and typography”| Change | File |
|---|---|
| Sidebar wordmark, navigation, search and shared shell | src/app/App.tsx |
| Account-page wordmark and setup screens | src/features/AccountFlows.tsx |
| Default workspace name, tagline, view, density and appearance | src/data/entities.ts |
| Document title, metadata, initial appearance and favicon link | index.html |
| Favicon | public/favicon.svg |
| Font and stylesheet imports | src/main.tsx |
| Light palette, typography and base UI | src/styles.css |
| Dark palette and component overrides | src/theme.css |
| Business modules, tables and invoice print layout | src/business.css |
| Project cover sizing and compact density | src/covers-density.css |
| Page and collection transitions | src/motion.css, src/components/MotionGroup.tsx |
Update the light and dark values for --canvas, --panel, --ink, --muted, --line, --accent and --accent-light together. Check explicit component colors, badges, chart labels and focus rings after changing the palette.
Plus Jakarta Sans is bundled locally through Fontsource. To change it, update the font import and the --font-sans token, and retain the license notices for any fonts you distribute.
Appearance supports Light, Dark and System. The early script in index.html applies the saved choice before the app renders. Keep it aligned with WorkspaceProvider.tsx if you change the persistence key or appearance behavior.
Replace artwork
Section titled “Replace artwork”Project covers live in public/images/projects/. Each artwork key has two files, for example orbit.jpg and orbit-small.jpg. The included sizes are 1536 × 1024 and 768 × 512.
Replace both files with artwork of similar proportions. Keep text in the interface rather than baking project names into the image. Adding a new artwork key also requires updating the project schema, seed data and related selectors. The package’s docs/PROJECT-IMAGES.md records the included artwork’s provenance.
Edit sample data and plans
Section titled “Edit sample data and plans”src/data/workspace.ts: workspace schema, project/member seed data, reducer and restoration.src/data/entities.ts: clients, tasks, notifications and default preferences.src/data/business.ts: opportunities, invoices, tickets, plans, subscriptions, integrations, keys, reports and audit entries.src/data/analytics.ts: sample reporting records, filters, aggregations and event fixtures.
Extend schemas, types, forms and migrations together. The business subtree defaults into older workspace saves without resetting existing projects or preferences. Keep foreign-key relationships intact when changing sample records.
For an empty starting workspace, update all relevant seed arrays, including the business modules, and retain the current member and required settings. Validate the result with workspaceSchema and check both fresh-start and reset behavior.
Add or remove modules
Section titled “Add or remove modules”Routes and navigation live in src/app/App.tsx; the browser router is created in src/main.tsx. Add a feature under src/features/, then connect its route, navigation entry and page title. Authentication uses a separate layout branch.
When removing a module, also update global search, dashboard links, client-detail links and onboarding destinations that point to it. Keep the shared provider as the single state source for related records.
Use src/components/BusinessUI.tsx for business panels, metrics, pills, form dialogs, simulated save handling, tables and CSV export. Shared dialogs, pending fields and empty states also live in src/components/ui.tsx.
Connect your backend
Section titled “Connect your backend”The included data flow is:
Form → validation → simulated save → typed action → shared reducer → workspace state → browser persistencesrc/app/WorkspaceProvider.tsx exposes state, dispatch, notifications and the simulated request lifecycle. run accepts a synchronous callback, waits 450 ms and optionally fails once through the Demo guide’s error toggle.
Replace this lifecycle with an awaited service request. Validate the server response, update shared state with canonical IDs and dates, then show success and close the form. Keep submitted drafts on failure and prevent duplicate submissions while a request is pending. Simply passing an asynchronous function into the existing run helper does not make it await that request.
| Capability | Service work to connect |
|---|---|
| Accounts and roles | Authentication provider, sessions, account recovery and server-enforced permissions |
| Workspace data | Authorized reads/writes, persistence, validation and conflict handling |
| Files | Upload bytes, store object references and authorize previews/downloads |
| Invitations and support | Invitation tokens, email delivery and conversation storage |
| Plans and payments | Checkout, subscription updates, payment events and canonical billing records |
| Analytics | Event collection, reporting queries, retention cohorts and aggregation rules |
| Integrations and keys | OAuth or API connections, real credential issuance, scopes and revocation |
| Security and audit | Enforced verification, actual session revocation and durable server audit records |
Search every dispatch( call site when integrating: some immediate controls dispatch directly rather than using the form-save helper. Remove or adapt the browser persistence, demo reset, failure simulator and fictional fixtures when your server becomes authoritative.
File additions currently save metadata only. Integration toggles do not call external services. Demo keys cannot access an API and only their suffix is persisted. Role labels, verification preferences and sample sessions are interface examples; access must be enforced by your backend. The audit list retains the latest 100 local business actions.
Verify your changes
Section titled “Verify your changes”npm testnpm run buildnpm run test:e2eThe package includes 18 state tests and 38 Chrome browser journeys, verified from a clean 0.2.0 extraction on macOS. Browser tests use installed Google Chrome by default and isolated browser contexts.
For Playwright’s Chromium on macOS/Linux:
npx playwright install chromiumPLAYWRIGHT_CHANNEL=chromium npm run test:e2eTo run against an isolated development port on macOS/Linux:
CI=1 PLAYWRIGHT_PORT=5177 npm run test:e2eAfter customization, check the affected workflows, keyboard navigation, mobile layouts, light/dark appearance, compact density and reduced motion. When adding services, also exercise request failures, session expiry and unauthorized access.
Deploy the app
Section titled “Deploy the app”Deploy the contents of dist/ to your static host. The supplied build targets the root of an origin, such as https://app.example.com/.
Configure the host to serve real assets normally and return index.html for application routes such as /projects/orbit or /invoices/inv-1042. Confirm that directly opening and refreshing a detail URL works.
Subdirectory hosting requires coordinating Vite’s base, React Router’s basename in src/main.tsx, root-relative asset URLs and host rewrites. Changing only the Vite base is insufficient. The build itself does not deploy anything.
Troubleshooting
Section titled “Troubleshooting”| Symptom | What to check |
|---|---|
504 Outdated Optimize Dep after dependency changes | Stop the dev server, run npm run dev -- --force, then reload. |
| Port already in use | Run npm run dev -- --port 5175 --strictPort. |
| Another local application appears | Use the exact 127.0.0.1 URL printed by Vite. |
| Changed seed data does not appear | Reset sample data or use a fresh browser profile. Reset discards local edits. |
| Built preview shows old content | Run npm run build again before previewing. |
| Detail page returns 404 after deployment | Check the host’s SPA fallback. |
| Changes disappear between visits | Check browser storage availability and that you are using the same origin. |
The persistence key is aerolaunch.forma.workspace.v1. The demo does not synchronize records across tabs, devices or accounts. Invalid saved data restores a fresh sample workspace with a notice.
For help, email hello@aerolaunch.app with your Forma version, Node version, browser, exact command or steps, and the error output. Include your Lemon Squeezy order reference for download questions.