Skip to content

DHLM / Personal intelligence system

My digital life.
One intelligence layer.

I built DHLM to bring the information I actually need into one private workspace—connecting approved sources, useful AI assistance, and deliberate human control.

DHLM · ChatIllustrative preview · Synthetic data

Request: What’s on my calendar this week?

Router
  • Calendar (fetched)
  • Gmail (not needed)
  • Drive (not needed)
  • Notes (not needed)
  • Tue 10:00Design review
  • Thu 2:00Northwind interview
  • Fri 9:30Harbor project sync

Answer: Three events through Friday. The earliest is Tuesday’s design review at 10:00.

L1 Calendar · read-only

  • DHLM / Public case study
  • Built by Davis Higgins
  • Charlotte, NC
  • Private · Single user

01 / Why I built it

The information existed. The workflow didn’t.

My work moves between school, analytics, software projects, business, and career planning. The context I need rarely lives in one place. An email contains one detail, a calendar event another, and a file holds the rest.

DHLM is my answer to that fragmentation: a focused place to ask better questions, retrieve relevant information, and turn scattered context into a clearer next step.

  1. Fragmented sources becomes Connected context

    Gmail, Calendar, Drive, and my own notes can answer one question together.

  2. Repeated searching becomes Focused retrieval

    A rule-based router decides which sources a question needs. Nothing else is fetched.

  3. Powerful tools becomes Explicit boundaries

    Read-only by default. Writing needs a separate grant and a confirmation every time.

Inside DHLM

Step inside the workspace.

One private workspace. Every approved source, one question away.

02 / What DHLM supports

Built around the way I work.

Every workflow starts with a plain request. DHLM works out which approved sources that request needs, fetches only those, and answers with the sources attached.

  1. live · gmail

    Email context

    “Find the message about the upcoming interview.”

    Searches Gmail read-only with a query built from the request, then reads only the messages the answer needs.

    • gmail.readonly
    DHLM · Email context

    Request: Find the message about the upcoming interview.

    route: live · gmailgmail.readonly

    • Avery Chen · Northwind AnalyticsInterview confirmed — Thursday 2:00 PMTue 9:14
    • Northwind Talent TeamYour application was receivedMon 4:02

    Avery Chen confirmed a 45-minute interview for Thursday at 2:00 PM and asked you to bring one analytics project to discuss L1.

    • L1Interview confirmed — Thursday 2:00 PM · avery@northwind.example.com

    Illustrative preview · Synthetic data

  2. live · calendar

    Calendar clarity

    “What is coming up this week?”

    Lists the next seven days of events from Google Calendar. Scheduled events are shown as events; anything the model suggests is labeled as a suggestion.

    • calendar.readonly
    DHLM · Calendar clarity

    Request: What is coming up this week?

    route: live · calendarcalendar.readonly

    • Design reviewTue 10:00 – 10:45Event
    • Northwind interviewThu 2:00 – 2:45Event
    • Prepare interview project notesWed eveningSuggestion

    Two events this week: the design review Tuesday at 10:00 L1 and the Northwind interview Thursday at 2:00 L2. Suggestion, not on your calendar: set aside time Wednesday to prepare.

    • L1Design review · Tue 10:00
    • L2Northwind interview · Thu 2:00

    Illustrative preview · Synthetic data

  3. live · drive

    File discovery

    “Find the notes for this project.”

    Searches Drive file names and metadata, then reads Google Docs, Sheets, Slides, or plain-text files when asked.

    • drive.readonly
    DHLM · File discovery

    Request: Find the notes for this project.

    route: live · drivedrive.readonly

    • Harbor Dashboard — working notesGoogle Doc · edited 2 days agoDoc
    • Harbor metrics draftGoogle Sheet · edited last weekSheet

    The working notes are in “Harbor Dashboard — working notes” L1. The latest section lists three open questions about the metrics definitions L2.

    • L1Harbor Dashboard — working notes · Google Doc
    • L2Harbor metrics draft · Google Sheet · read as CSV

    Illustrative preview · Synthetic data

  4. career · applications

    Job-search tracking

    “Which applications need my attention?”

    The career workspace keeps application records. A Gmail sync I run labels recruiter, interview, and confirmation emails with rules and links them to applications for review.

    • gmail.readonly
    DHLM · Job-search tracking

    Request: Which applications need my attention?

    route: career · applicationsgmail.readonly

    • Northwind Analytics · Data Analyst InternInterview requestedNeeds reply
    • Lumen Labs · Analytics EngineerSubmitted 12 days agoFollow up
    • Cobalt Studio · Product AnalystApplication receivedWaiting

    Two need attention: reply to Northwind’s interview request C1, and consider a follow-up with Lumen Labs—it has been 12 days since you applied C2.

    • C1Northwind Analytics · interview_request · linked email
    • C2Lumen Labs · submitted · no reply yet

    Illustrative preview · Synthetic data

  5. draft · confirm required

    Assisted drafting

    “Help me draft a reply.”

    Drafts in my writing style. Saving it to Gmail is an optional, separately granted action with a preview and a one-time confirmation. DHLM never sends email.

    • gmail.compose · optional
    DHLM · Assisted drafting

    Request: Help me draft a reply.

    route: draft · confirm requiredgmail.compose · optional

    • To: avery@northwind.example.comRe: Interview confirmed — Thursday 2:00 PM
    • Thanks, Avery — Thursday at 2:00 works well.I’ll bring the Harbor dashboard project to walk through.

    Here’s a short reply in your style. Review it, then choose “Create Gmail draft” to prepare it. Nothing is sent.

    • K1Writing style · knowledge file

    Prepare → review exact preview → confirm within 5 minutes → draft saved. Sending stays manual.

    Illustrative preview · Synthetic data

  6. quick action · on request

    Morning brief

    “Give me my morning brief.”

    A quick action I run when I want it: calendar, recent email, and my current priorities in one answer. It is not a scheduled job.

    • calendar.readonly
    • gmail.readonly
    DHLM · Morning brief

    Request: Give me my morning brief.

    route: quick action · on requestcalendar.readonlygmail.readonly

    • TodayDesign review at 10:00Event
    • EmailInterview confirmation from NorthwindNew
    • PriorityFinish the Harbor dashboard draftNotes

    Design review at 10:00 L1. Northwind confirmed Thursday’s interview L2. Your top priority is still the Harbor dashboard draft K1.

    • L1Design review · Today 10:00
    • L2Interview confirmed · Northwind
    • K1Current priorities · knowledge file

    Illustrative preview · Synthetic data

03 / Request architecture

A question becomes a focused workflow.

Simplified architecture. The case study uses synthetic data.

  1. 01Ask

    A request enters a bounded workspace.

    Every chat request passes the same gate: a signed session for the one authorized account, a same-origin check, and a rate limit. A rule-based router then classifies the question and names the sources it needs.

    01 Ask

    “What’s on my calendar this week, and did the recruiter reply?”

    • Signed session
    • Same origin
    • Rate limit

    route: live · calendar, gmail

    Synthetic

  2. 02Authorize & retrieve

    Only the approved sources light up.

    Live data is fetched in parallel, once per source, and only if the connected Google grant includes that read scope. Personal notes come from a ranked search over my own Markdown knowledge files.

    02 Authorize & retrieve

    • calendar.readonly3 events
    • gmail.readonly2 messages
    • drive.readonlyNot needed
    • Fetched in parallel, once per source

    Synthetic

  3. 03Assemble & reason

    Context becomes a precise prompt.

    DHLM assembles a system instruction, the ranked notes with their precedence, and the live results, then streams a response from Gemini. A daily budget decides whether a deeper model is allowed.

    03 Assemble & reason

    • K1 Current priorities
    • K2 Career notes
    • L1 Calendar · 3 events
    • L2 Gmail · 2 messages

    Gemini · default model · streaming

    daily budget: within limit

    Synthetic

  4. 04Return & review

    The answer arrives with its sources.

    Sources appear beside the streamed answer and usage is logged. Anything that would change an account—a draft, an event, a memory update—stays a separate step that I review and confirm.

    04 Return & review

    Three events this week, including Thursday’s interview L1. The recruiter replied Tuesday to confirm the time L2.

    L1 Calendar L2 Gmail

    Create draft reply?review → confirm · single use

    Synthetic

04 / What I built

More than a chat interface.

I designed and built the application, the integrations, and the controls around them. Google provides the data APIs and the Gemini models; DHLM decides what to ask them, when, and with which permission.

Davis HigginsApplication, integrations, and controls by Davis Higgins

  1. BrowserPages and streamed answers
  2. DHLM serverProxy gate · route handlers · router
    • Google APIsGmail · Calendar · Drive
    • GeminiGoogle Gen AI SDK
    • SupabasePrivate Postgres
Every request goes through the DHLM server. The browser never talks to Google APIs, Gemini, or the database directly.
  1. Application layer

    Server-rendered pages, streaming route handlers, and one gate in front of everything.

    How the app is structured

    • DHLM is a Next.js App Router application in strict TypeScript. Pages render on the server; the chat, command palette, and integration controls are client components.
    • Chat answers stream as newline-delimited JSON events—route details, sources, text, and usage—so sources can appear before the answer finishes.
    • A proxy gates every page and API route, and each handler re-checks the session before doing any work.
  2. Google integration layer

    Service-specific clients that check the granted scope before every call.

    What the integrations actually read

    • Gmail, Calendar, and Drive each have their own client, sharing one OAuth client per grant that refreshes access tokens on the server.
    • Each fetch checks for the scope it needs and reports a missing permission instead of failing silently. An expired grant becomes a reconnect prompt.
    • Drive reads Google Docs and Slides as text, Sheets as CSV, and plain-text files under 2 MB. Other formats are found by name and metadata only.
  3. Gemini layer

    A configured model, a strict prompt, and a daily budget.

    How requests reach the model

    • The Google Gen AI SDK runs only on the server, so the API key never reaches the browser.
    • A fast default model answers most requests. A deeper model is used only when I ask for it and the daily budget allows. Answers stream as they are generated.
    • Personal notes are retrieved with local keyword ranking by default; Gemini File Search can be used instead when it is configured. I built the integration—the model itself is Google’s.
  4. Persistence layer

    Private Postgres tables that only the server can reach.

    What is stored, and where

    • Supabase Postgres holds conversations, usage, audit events, settings, proposed memory updates, single-use confirmation records, and career-tracking records.
    • Only server code talks to the database; nothing in the browser holds database credentials.
    • Gmail, Calendar, and Drive content is fetched when a request needs it. Job-search email details are kept only when I run a career sync.
  5. Quality and operation

    Deterministic where it matters and tested where it could break.

    Validation, tests, and scheduled work

    • Zod validates request bodies and configuration. Unit tests cover retrieval precedence, permissions, confirmation tokens, memory promotion, and career policy.
    • Playwright tests exercise the main flows against a mocked Gemini, so they run without API keys or spend.
    • A daily scheduled job handles job discovery and data retention. It never touches Gmail or Calendar.

05 / Authentication and control

Access is intentional. Actions are explicit.

Identity

Google sign-in establishes who I am. It asks only for a basic profile, and the server compares the verified email with the one authorized account. Anyone else is turned away.

openid · email · profile

Integration permissions

Gmail, Calendar, and Drive are connected in a separate consent step with read-only scopes. Signing in does not hand DHLM my inbox or my files.

gmail.readonly · calendar.readonly · drive.readonly

Google permissions as implemented
ServiceDefaultOptional actionBoundary
Google identityBasic profile onlyNoneOne authorized account, checked on the server
GmailRead-only search and read, when connectedCreate drafts, if enabledPreview and confirmation; never sends
CalendarRead-only upcoming events, when connectedCreate events, if enabledPreview and confirmation
DriveRead-only search and supported text, when connectedNoneDocs, Sheets, Slides, and text under 2 MB
  • Tokens stay sealed

    The Google refresh token lives in an encrypted, HTTP-only cookie—not in the database.

    Grants and OAuth state are sealed with AES-256-GCM. The session is a signed token in an HTTP-only, same-site cookie that is marked secure in production.

    Sign-in uses PKCE and a one-time state value that expires after ten minutes.

  • Writes take two steps

    Drafts and events are prepared, previewed, and then confirmed with a single-use token.

    The prepare step returns the exact preview and a signed token bound to that action and a hash of its details. It expires in five minutes and can be used once.

    If anything in the draft or event changes after review, the token no longer matches and the action is refused.

  • Access can be revoked

    Disconnecting revokes the token at Google and deletes the local cookie.

  • Changes are recorded

    Sign-ins, denied sign-ins, connections, and every prepared or executed write are written to an audit log.

  • Memory is proposed, not written

    The assistant can suggest updates to what DHLM knows about me. Nothing changes until I approve it.

Relevant context may be sent to Google Gemini to generate a response. DHLM keeps that processing tied to the signed-in user’s request. Read the privacy policy.

Limits

Perspective & boundaries

06 / Perspective and limits

DHLM is a private system built around my workflows—not a public multi-user service. Its value comes from connecting useful information with clear boundaries, not giving an AI unrestricted access.

  • Supported files only

    Drive answers draw on Google Docs, Sheets, Slides, and plain-text files under 2 MB. Other formats are found by name, not read.

  • Connections can lapse

    If Google access expires or a scope is missing, DHLM says so and asks me to reconnect instead of guessing.

  • Answers can be wrong

    A model can misread context or miss something. Sources sit beside each answer so I can check it.

  • Optional means optional

    Drafts and calendar events stay off until I grant them separately, and each one still needs confirmation.

Useful AI. Clear boundaries.

DHLM at a glance

The numbers that define the boundary: what DHLM can reach, who can use it, and what it will never do on its own.

  • 3

    Google services connected, each read-only by default

    Gmail · Calendar · Drive

  • 1

    Authorized account, checked on every page and API route

    Single user

  • 5

    Minutes to confirm a draft or event before its token expires

    Single-use confirmation

  • 0

    Emails sent by DHLM. It drafts; sending stays manual

    Human directed

Built with

  • Next.js 16

    Application framework

  • React 19

    Interface

  • TypeScript

    Strict mode throughout

  • Tailwind CSS 4

    Private app styling

  • Google Gen AI SDK

    Gemini, server-side only

  • Gmail API

    Read-only by default

  • Calendar API

    Read-only by default

  • Drive API

    Read-only by default

  • Supabase Postgres

    Server-only persistence

  • Zod

    Request and config validation

  • Vitest

    Unit tests

  • Playwright

    End-to-end tests

  • Vercel

    Hosting