User Guide
Walks through every feature in LaraContact from the user's perspective. If you're a developer installing the app, see the Installation Guide first.
1Signing in
- Navigate to your install URL.
- The landing page has Sign in and Get started buttons.
- Registering creates your personal workspace automatically β there's no separate "create company" step.
- If your admin has disabled public registration, you'll only see Sign in. You'll need an invitation from a workspace owner.
Forgot your password? Click Forgot? on the login page. A reset link is emailed to you (provided mail is configured).
2The dashboard
The dashboard is your daily home. Top to bottom:
- π Getting started checklist β A 6-step onboarding card with progress bar. Each step links you to the relevant page. Dismiss it once you're set up.
- Hero strip β Greeting + quick-action buttons (Add contact, Compose email, Import, Template).
- KPI cards β Contacts, Messages, Calls, Emails β with a month-over-month delta chip (green up, red down, grey flat).
- Pipeline β Contacts grouped by lifecycle stage (lead, prospect, customer, partner, vendor) with progress bars.
- Recent activity β A unified feed of SMS, WhatsApp, calls, and emails.
- Today's reminders β Top 3 due, with an overdue counter.
- π₯ Hot prospects β Contacts auto-filtered by tags like
vip,hot,enterprise,follow-up. - π Birthdays β Upcoming contact birthdays.
3Working with contacts
3.1 Adding a contact
- Manually: Click Add contact on the dashboard or
/contacts. Fill in the form. Only Name is required. - From a paste: On the create page, paste an email signature, LinkedIn snippet, or business card text into the AI-assisted fill box and click Suggest fields. The form auto-populates name, email, phone, company, job title, website, and LinkedIn.
- From CSV: See Β§4 Importing from CSV.
3.2 The contact form fields
- Basics: name (required), email, phone, company, job title, website, address
- Lifecycle stage: lead / prospect / customer / partner / vendor β drives the dashboard pipeline view
- Birthday: shown on the dashboard birthday card
- Group: contacts belong to one group (Customers, Leads, etc.)
- Tags: many-to-many labels (VIP, follow-up, etc.). Click β¨ Suggest from context to have AI propose tags based on the contact's notes + company + title.
- Social: optional Twitter, LinkedIn, Facebook handles
- Notes: free-text scratchpad
- Custom fields: per-contact key/value pairs. Click Add field to create a new row (e.g. "Birthday gift idea" β "Coffee tour").
3.3 Viewing a contact
Open any contact to see:
- Left rail: avatar, name, title, company, lifecycle badge, group, key contact details, tag chips.
- Tabs:
- Activity β chronological feed of all SMS, WhatsApp, calls, and emails with this contact
- Notes β the free-text notes you wrote
- Custom fields β your custom key/value pairs
- Action bar (top right): Call (logs a call entry), SMS (opens the message thread), Edit, and a β― menu with Delete.
- If duplicates of this contact exist in your workspace (same email or phone), a β Potential duplicate banner appears with a Review & merge button.
3.4 Searching and filtering
- Search bar: matches name, email, phone, or company (server-side)
- Group filter: dropdown of your groups
- Tag chips: click any tag at the top of the page to filter; click again to unfilter
- Command palette (βK): global search from anywhere
3.5 Bulk operations
Select multiple contacts via the checkbox column. A sticky action bar appears:
- Add to group β bulk-assign a group
- Add tag β bulk-tag
- Send message β opens the bulk-send composer (Email / SMS / WhatsApp). See section 6.
- Delete β soft-delete (recoverable from DB)
3.6 Duplicate merge
Open a contact, look for the β Potential duplicates banner. Click Review & merge, check the boxes for the duplicates you want to absorb, and submit. Behavior:
- Blank fields on the kept contact get filled from duplicates
- All tags are combined
- All SMS, WhatsApp, calls, and emails are reassigned to the kept contact
- Duplicate records are hard-deleted
The whole operation runs in a transaction β if any step fails, nothing changes.
4Importing from CSV
- From the dashboard, click Template to download
contacts-import-template.csvwith the right headers + one example row. - Fill in your rows. Required column: Name. Optional: Email, Phone, Company, Job title, Website, Address, Notes, Tags (comma-separated, e.g.
vip, follow-up). - Click Import (dashboard) or Import CSV (
/contacts/import). - Upload your file. The preview page auto-detects which CSV column maps to which contact field. Adjust if needed.
- Optionally assign the entire batch to a group via the dropdown.
- Click Import contacts.
5Communication
5.1 SMS and WhatsApp
- Go to Messages in the sidebar, or click SMS on a contact.
- The thread view shows iMessage-style bubbles. Outbound messages use your primary color; WhatsApp is green; inbound is muted grey.
- Type your message, choose SMS or WhatsApp in the toggle, click Send.
- AI assist buttons inline:
- Fix β rewrites your message to correct spelling and grammar (preserves voice)
- Translate β pick from 9 languages
- Two-way SMS: when a contact replies to your Twilio number, the message arrives in the thread automatically and a toast notification appears in any open browser session. The page title also gets a
β’prefix until you click back to that tab.
In fake mode (no Twilio credentials configured), messages are recorded with a FAKE... SID and the UI shows a banner. Inbound webhook still works β useful for testing.
5.2 Calls
- Go to Calls in the sidebar.
- The dialer pad accepts manual numbers, or click Call on any contact to log a call.
- Browser-based voice calling requires real Twilio credentials + a TwiML Application SID configured in Settings β Twilio.
- The right side shows recent call history with status badges.
5.3 Email
- Go to Email in the sidebar β click Compose.
- Search and pick a contact via the autocomplete field.
- Write subject + body. Email is queued and dispatched via your configured mail driver.
- The email contains an invisible tracking pixel β once the recipient opens it, the Opens column in
/emailsincrements.
6Bulk sends
Send a single composed message β Email, SMS, or WhatsApp β to many contacts at once, with mail-merge personalization.
6.1 Composing a bulk send
- Go to Contacts, tick the checkboxes for the contacts you want to message.
- In the sticky action bar that appears, click Send message.
- Pick a channel:
- Email β HTML/plain via your configured mail driver. Has a Subject field.
- SMS β Twilio SMS. Messages over 160 chars split into segments.
- WhatsApp β Twilio WhatsApp Business. No hard length cap.
- Compose your body using merge tokens to personalize per recipient:
{{first_name}}β first word of the contact's name{{name}}β full name{{company}}{{email}}{{phone}}
- Hit Send. Contacts missing the channel's required field (no email / no phone) are silently skipped β the toast tells you how many.
6.2 Tracking progress
After sending, you land on the Bulk send detail page (/bulk-sends/{id}) which shows:
- Real-time counters: total / sent / failed
- Progress bar (gradient primaryβfuchsia)
- The message template you used (so you can copy it for next time)
- Full recipient list with avatars
The page auto-refreshes every 4 seconds while the send is still running.
6.3 Past sends
Open Bulk sends in the sidebar (under Communication) for a paginated history with status badges, sent/failed counts, and preview text. Click any row to drill in.
6.4 Reusable templates
On the composer, tick Save as template for next time and give it a name. Next time you open the composer, the saved templates appear as clickable chips at the top β click one to instantly populate the channel, subject (email only), and body. Templates are workspace-scoped, so every member sees the same library.
Delete a template via DELETE /bulk-sends/templates/{id} or by removing it from the chip strip on the composer (UI hover).
app/Providers/AppServiceProvider.php). Every successful send creates a normal Message or EmailMessage row, so each send still shows up in the contact's history.
php artisan queue:work under a process supervisor (systemd, Supervisor) so messages dispatch in the background instead of during the HTTP request.
7AI-assisted workflows
LaraContact integrates with Anthropic Claude for four user-facing features. All work in fake mode (heuristic fallbacks) if no API key is set.
| Feature | Where to use it | What it does |
|---|---|---|
| Contact enrichment | /contacts/create β AI-assisted fill card | Paste signature/text β extracts name, email, phone, company, title, website, LinkedIn |
| Spell-check & grammar fix | SMS thread composer β Fix button | Rewrites your message correctly without changing voice |
| Translation | SMS thread composer β Translate button | 9 languages (English, Spanish, French, German, Italian, Portuguese, Chinese, Japanese, Arabic) |
| Tag suggestion | /contacts/create β Tags card β Suggest from context | Picks the best-fitting tags from your workspace's library based on notes + company + title |
Configure your Anthropic API key in Settings β AI. Click Test AI connection to verify.
8Reminders and follow-ups
7.1 List view (/reminders)
Pending reminders grouped by:
- Overdue (red badge)
- Today (amber)
- This week
- Later
Each row has a circle to mark complete and a Delete button. The footer shows recently completed reminders, dimmed and struck through.
7.2 Calendar view (/reminders/calendar)
Monthly grid. Click any day to schedule a reminder for that date β a modal pops up. Each day shows up to 3 reminder chips colored by status. Use the arrows to navigate months, or the Today button to jump back.
7.3 Notifications
Reminders fire via the reminders:send-due scheduled command (runs every 5 minutes). When a reminder is due:
- If Email me is checked β an email is sent to the reminder's owner
- If SMS me is checked and your user profile has a phone β an SMS is sent via Twilio
Each reminder is notified only once, then marked notified_at.
9Workspace and team invitations
LaraContact supports multiple workspaces per user. Each workspace has its own contacts, tags, groups, settings, and audit log.
9.0 Exporting your workspace
Top-right of the Members page, click Export data. You'll download a ZIP containing CSV files of every contact, message, email, reminder, group, and tag in the current workspace, plus a README.txt manifest with row counts. Great for backups, migrations, or buyer offboarding.
9.1 Inviting a teammate
- Owner only.
- Go to Workspace β Members in the sidebar.
- Enter their email + role (Admin or Member) β Send invite.
- They receive an email with an accept link. The link is valid for 7 days.
- Once they accept, they appear in the members list with their role badge.
8.2 Removing a member
Owner only. Click Remove on any member row. The owner cannot be removed. If the removed user had the workspace set as their current workspace, they're auto-switched to their personal workspace.
8.3 Switching workspaces
Click the workspace name in the sidebar header β dropdown lists every workspace you belong to β click to switch. Your current workspace ID is saved on your user record.
8.4 Public registration toggle
The owner can disable public registration in Settings β General. When off, the /register URL returns 404 and the Create account link disappears from the login page. The only way to onboard new users becomes a team invitation.
10Library: Groups and Tags
9.1 Groups
A contact can belong to at most one group. Use for big-picture buckets (Customers, Leads, Partners). Each group has a color shown in the contact list.
/groupsβ list, inline create, inline edit, delete- Deleting a group does NOT delete its contacts; their
group_idis set to null
9.2 Tags
A contact can have many tags. Use for flexible labels (VIP, hot, follow-up, referral). Each tag has an accent color and an auto-generated slug.
/tagsβ list, inline create, inline edit, delete- Tag names must be unique per workspace
- Tags used in CSV imports are auto-created if missing
11Audit log
/audit shows every change to every contact in this workspace: who, what, when. The diff renders old and new values for every changed field.
Powered by spatie/laravel-activitylog. The Contact model uses logOnlyDirty and dontSubmitEmptyLogs so the log isn't spammed with no-op saves.
12Two-factor authentication
Optional but recommended. Adds a 6-digit code prompt after every password sign-in.
12.1 Setup
- Profile β Two-factor authentication β Set up 2FA.
- Scan the QR with any TOTP app (Google Authenticator, 1Password, Authy, Bitwarden, iOS Passwords).
- Save the 8 recovery codes shown below the QR β each is single-use and required if you lose access to your authenticator.
- Enter the 6-digit code your authenticator shows, then Confirm.
12.2 Sign-in challenge
On every login attempt against an account with confirmed 2FA, after the password is validated the user is redirected to /two-factor-challenge. They enter the OTP (or toggle to Use a recovery code instead) to finish signing in. The session is held in two_factor.pending_user_id until verification β failed verifications don't authenticate them.
12.3 Recovery codes
Eight codes generated at setup, encrypted at rest. Each is consumed on use; remaining count is shown on the Profile β Two-factor page. Out of codes? Disable 2FA from the same page and re-enable to get a fresh set.
12.4 Locked out
Lost the authenticator AND all recovery codes? An admin with database access can clear the user's 2FA fields:
php artisan tinker --execute='\App\Models\User::where("email","you@example.com")->update(["two_factor_secret"=>null,"two_factor_confirmed_at"=>null,"two_factor_recovery_codes"=>null]);'
That user can then sign in normally with just their password.
App\Support\TwoFactor::verify() if your environment needs more.
13Settings reference
Click your avatar β Settings, or the Settings link in the sidebar.
General
- App name, tagline, locale
- Footer text (shown on landing page)
- Public registration toggle
Branding
- Logo upload (PNG / JPG / SVG / WebP, max 2 MB)
- Primary color β drives every button, link, and accent in the entire app (live-applied via CSS custom properties)
- Email signature β appended to outbound contact emails
- Mailer driver (log, SMTP, Resend, Mailgun, Postmark, SES)
- From email + name
- SMTP host/port/user/encrypted-password/encryption
- API drivers: encrypted API key + (Mailgun) domain
- Send test email button
Twilio
- Fake mode toggle
- Account SID + Auth Token (encrypted)
- Phone number, API Key SID/Secret (encrypted), Application SID
- Inbound webhook URL is shown β copy it into your Twilio Console
AI
- Fake mode toggle
- Anthropic API key (encrypted)
- Model selector (Opus 4.7 / Sonnet 4.6 / Haiku 4.5)
- Max tokens
- Test AI connection button
14Public JSON API
LaraContact exposes a Sanctum-protected JSON API.
Creating a token
- Click your avatar β API tokens.
- Click Create token, give it a name. The token is shown once; copy it before navigating away.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/user | Current authenticated user |
GET | /api/contacts | Paginated contacts (?q=, ?per_page=25) |
GET | /api/contacts/{id} | One contact with relations |
POST | /api/contacts | Create contact |
PUT | /api/contacts/{id} | Update contact |
DELETE | /api/contacts/{id} | Soft-delete contact |
Example
curl -H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json" \
https://yourdomain.com/api/contacts
Rate limit
60 requests/minute per token. Exceeded requests get 429 Too Many Requests with a Retry-After header.
15Keyboard shortcuts
| Shortcut | Action |
|---|---|
| βK / Ctrl+K | Open command palette (global search + nav) |
| β / β | Navigate within command palette |
| Enter | Open selected result |
| Esc | Close any modal or palette |
16Frequently asked questions
My SMS sends say FAKE... and don't actually arrive on phones.
You're in fake mode (no Twilio credentials). Go to Settings β Twilio, paste your Account SID, Auth Token, and phone number, and uncheck Fake mode.
I added an Anthropic API key but AI still seems to fall back.
Make sure Fake mode is unchecked in Settings β AI. Also use the Test AI connection button to confirm the key works.
How do I export my contacts?
Not currently built into the UI. You can pull them via the JSON API, or run SELECT * FROM contacts WHERE team_id = ? against your database. CSV export is on the roadmap.
Can I import vCards?
Not yet β only CSV. vCard support is on the roadmap.
Reminders never email me even though they're overdue.
Verify the scheduler is running. On a managed host that's a cron entry; in dev that's php artisan schedule:work in a separate terminal. See the Installation Guide.
Where are uploaded logos stored?
storage/app/public/branding/. Make sure you ran php artisan storage:link so they're served from public/storage/branding/.
Can I customize the email templates?
Yes β they live in resources/views/emails/. Edit them directly. The current templates are minimal inline-styled HTML.
Does it work on mobile browsers?
Yes. The sidebar collapses into a slide-over on small screens, tables hide secondary columns, and the dashboard re-stacks into a single column.
Is dark mode supported?
Yes β toggle it via the moon/sun icon in the top bar. Your preference is saved in localStorage and respected on next visit. System preference is honored on first load.
Can the same user belong to multiple workspaces?
Yes. Accept multiple team invitations, then use the workspace switcher in the sidebar header to flip between them.