TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A browser-based task manager for creating and editing tasks, assigning users,
setting priorities and due dates, marking tasks complete, and deleting tasks.
Drag and drop tasks to reorder them. Due-date colors and pulsing overdue tasks
highlight upcoming and missed deadlines. If your device is set to reduce motion,
overdue tasks do not pulse and are marked with a red border instead. A task
whose due date is cleared shows "No due date" in the normal colour. Deadlines
follow the current date while the page stays open, with no need to reload.README 전문 보기 ↗A browser-based task manager for creating and editing tasks, assigning users, setting priorities and due dates, marking tasks complete, and deleting tasks. Drag and drop tasks to reorder them. Due-date colors highlight upcoming and missed deadlines, and overdue tasks have a pastel pink background. If your device is set to reduce motion, overdue tasks are also marked with a red border. A task whose due date is cleared shows "No due date" in the normal colour. Deadlines follow the current date while the page stays open, with no need to reload.
Tasks are saved in this browser using localStorage and restored on refresh. The sample tasks appear on your first visit, with due dates relative to that day. "Reset to sample tasks", below the task list, replaces the current tasks with a fresh sample set at once, without asking for confirmation. If browser storage is unavailable, tasks remain usable in memory, but changes will not persist.
Use the Assignee dropdown above the task list to show one user's tasks or "All assignees". Both completed and incomplete matching tasks remain visible. "All assignees" appears first, followed by users alphabetically by name. Each task's assignee dropdown uses the same alphabetical user order. Your selection is restored on refresh; a missing or unavailable assignee defaults to "All assignees". If storage is unavailable, the selection remains usable in memory. New tasks are assigned to the selected assignee. Under "All assignees", they default to the first available user. Dragging filtered tasks changes their order in the complete task list.
Dictate into a task title with the microphone button beside it, or press Ctrl and Alt together (with no other key) while editing a title. Press either again to stop. Recognised speech is inserted at the cursor, replacing any selected text, with a space added where it meets existing words. Words appear as you speak and may be corrected for a few seconds, including just after you stop. Moving the cursor, or moving to another task title, sends further speech there. Dictation stops automatically after a period without recognised speech (15 seconds by default), after a maximum time (60 seconds by default, counted from when the microphone starts recording), when focus leaves the task titles, or when the task being dictated is deleted. Recognised text may keep settling for up to four seconds after dictation stops. A line at the top of the page says how to start and stop dictating.
A status box above the task list shows what dictation is doing:
The level meter shows how loud the sound reaching the microphone is. It does not show whether speech was recognised, and a quiet meter is not an error. "Level meter", above the task list, chooses its style, and can be changed while dictating: "Horizontal bar" grows from the left, with a marker that holds the recent peak for about a second, "Analogue needle" sweeps a needle across an arc, and "Waveform" draws a row of thin vertical bars. "Look", on the line below, offers three looks for the style that is selected: Solid, Segments and Gradient for the bar, Classic, Zones and Ticks for the needle, and Pill, Pulse and Columns for the waveform. Pill and Columns scroll the last second or so of sound from right to left, Pill as white bars in a black pill and Columns as coloured bars rising from the bottom. In Pulse the bars stay in place and swell together. Each style keeps its own look. The choices last until the page is reloaded. The level is worked out in the browser from the audio already being captured, and is not stored or sent anywhere. With reduced motion set on the device, the meter moves in a few steps a second.
A line above the task list says "This demo may retain dictated text for diagnostics.", because the deployed app keeps the final recognised text; see Stored transcripts. Dictation needs setting up first; see Set up voice dictation.
You can sign in with a Google account, which is optional. Signed in, the page shows who you are and keeps a preferred name for you, but your tasks stay in this browser as before. See Sign-in with Google.
@speechmatics/real-time-client, @speechmatics/browser-audio-input and
@speechmatics/auth packages.With Node.js 20.19+ (20.x), 22.13+ (22.x), or 24+, and npm installed, run this from the project directory:
npm install
npm run dev
Open the local URL printed in the terminal. Sign-in shows as unavailable until it is set up; see Sign-in with Google.
Dictation uses the Speechmatics realtime API. Without this setup the app works as normal and the dictation buttons show that dictation is unavailable.
Create an API key in the Speechmatics portal.
Create .env.local in the project directory. It is ignored by git, so the key
is never committed:
SPEECHMATICS_API_KEY=your-api-key
Restart npm run dev (or npm run preview) after changing .env.local.
The key stays on the local Vite server. The browser only receives temporary keys
that expire after 60 seconds, from /api/dictation/token. Locally these
endpoints are served by npm run dev and npm run preview. The deployed app
serves the same endpoints as hosted functions; see Deployment.
Other dictation settings live in dictation.config.toml in the project
directory. It is committed, so it must never contain the API key, and each
setting is explained by a comment in the file:
| Setting | Default | Purpose |
|---|---|---|
[speechmatics] model | "enhanced" | Speechmatics model, such as "enhanced" or "standard". |
[speechmatics] language | "en" | Language code, such as "de", or a bilingual pack such as "cmn_en". |
[speechmatics] realtime_url | "wss://eu.rt.speechmatics.com/v2" | Realtime endpoint, for example the us or au region. |
[timings] inactivity_timeout_seconds | 15 | Stop after this many seconds without recognised speech. Sound that produces no recognised words does not count. |
[timings] max_session_seconds | 60 | Maximum length of one dictation session, from when the microphone starts recording. |
[timings] settle_timeout_seconds | 4 | How long recognised text may keep settling after dictation stops. |
One timing is fixed in the code and not in the file: connecting to Speechmatics may take up to 15 seconds from when the microphone starts recording. After that, dictation stops and reports that the service is unavailable.
Restart npm run dev or npm run preview after changing it. The server checks
the file when it starts and stops with a message naming the problem, such as a
misspelt setting or a timing that is not a positive number.
To change the model, language or endpoint on your machine only, set
SPEECHMATICS_MODEL, SPEECHMATICS_LANGUAGE or SPEECHMATICS_RT_URL in
.env.local; these override the file.
To try multilingual dictation with the Melia 1 realtime preview, set the model
to melia-1, the language to multi and the realtime URL to
wss://preview.rt.speechmatics.com/v2. Speechmatics provides
the preview for evaluation only, not production use, and it does not yet support
the custom dictionary that helps recognise the app's user names.
Microphone access needs a secure context, so open the app on localhost or over
HTTPS. The browser asks for microphone permission the first time you dictate.
The local server must be able to reach mp.speechmatics.com, and the browser
must be able to reach the realtime endpoint.
The app is deployed on Vercel as one project: the built front end, and the dictation endpoints as Vercel Functions on the same address. The browser connects directly to Speechmatics for realtime dictation, so the host only issues temporary keys.
api/dictation/status.ts, api/dictation/token.ts,
api/dictation/activity.ts and api/dictation/transcript.ts.
All four run the handler that local development uses, in
server/dictationHandler.ts.SPEECHMATICS_API_KEY
environment variable in the project's settings. The key must never be
committed to the repository or exposed in browser code. The same key can be
used for local development and the deployment. If the key is missing, the
deployed app remains usable but dictation is unavailable.dictation.config.toml, which
vercel.json deploys with the functions. SPEECHMATICS_MODEL,
SPEECHMATICS_LANGUAGE and SPEECHMATICS_RT_URL can be set in Vercel to
override it, as they can locally.tsconfig.json.npm run dev
it only logs to the browser console and records nothing.DATABASE_URL
environment variable, which Vercel sets when the database is connected to
the project. See Stored activity and
Stored transcripts.api/auth.ts,
api/account/status.ts and api/account/profile.ts, all through
server/accountFunction.ts. See Sign-in with Google
for their variables. Previews have no sign-in.To update the deployed app, push to the branch that Vercel deploys as production. Vercel builds and deploys it automatically. After changing an environment variable in Vercel, redeploy for it to take effect. Running the app locally needs no Vercel account or tools.
The app reports when dictation is used, so that activity on the deployed app
can be seen afterwards. The browser sends an event name and a testing label to
/api/dictation/activity. The server writes one line of JSON to its log and,
when deployed, saves the same three values to a database:
{"type":"dictation_activity","event":"dictation_transcript_received","user":"Dad","timestamp":"2026-10-08T15:30:00.000Z"}
| Event | What it shows |
|---|---|
dictation_started | The microphone was allowed and Speechmatics accepted the session. |
dictation_transcript_received | Speechmatics recognised at least one word. Logged once per session. |
dictation_completed | A started session ended normally: stopped by the user or by an automatic stop. |
dictation_failed | A session ended with an error, before or after it started. |
Transcript text, audio, keys, tokens and error messages are never written to the log. For activity events the server accepts only the four event names above and a valid testing label, and ignores everything else in a request. The final recognised text is kept separately; see Stored transcripts. Reporting is best-effort: if it fails, dictation carries on and nothing is retried.
To see the log, open the project in Vercel, choose Logs, and search for
dictation_activity. The Hobby plan keeps runtime logs for one hour, so the
log shows recent activity only. The database is the lasting record.
The deployed app saves each event to a Neon Postgres
database, added to the Vercel project through Vercel's Storage page. Vercel
gives the functions its connection string as the DATABASE_URL environment
variable. That string is a secret: it stays on the server, and must never be
committed or used in browser code.
Each activity row holds only the event name, the testing label and the time the server received it. No audio, key, token, IP address, user-agent or error message is stored anywhere.
One-time setup, after creating the database and connecting it to the project:
server/dictationActivity.sql
and run it. It creates the dictation_activity table, and is safe to run
again. The app never creates the table itself.DATABASE_URL.To inspect stored activity, use Neon's Tables view, or run a query in its SQL Editor:
-- The most recent events.
select occurred_at, user_label, event
from dictation_activity
order by occurred_at desc
limit 100;
-- Events per day, per label.
select occurred_at::date as day, user_label, event, count(*)
from dictation_activity
group by 1, 2, 3
order by 1 desc, 2, 3;
Things to know:
dictation_activity_store_failed and at most a database error code is
logged, and dictation is unaffected. 42P01 there means the table has not
been created.delete from dictation_activity where occurred_at < now() - interval '90 days';DATABASE_URL, as when running locally, events are only logged and
no database connection is attempted. npm run dev and npm run preview
never store events.The deployed app also keeps the words that Speechmatics recognised, so that you can see what a demonstration session produced. The app tells its users so, with the line "This demo may retain dictated text for diagnostics." above the task list.
/api/dictation/transcript with the text in the request body,
so that it does not appear in request logs, and saved as one row in the
dictation_session_transcripts table of the same Neon database.One-time setup: in Neon's SQL Editor, run the contents of
server/dictationTranscripts.sql. It adds the dictation_session_transcripts
table and is safe to run again. It changes nothing that exists, so the
dictation_activity table and any rows in dictation_transcripts are left
as they are. Until it has been run, transcripts are not stored, the log shows
dictation_activity_store_failed with code 42P01, and dictation is
unaffected.
To read stored transcripts:
-- Complete transcripts, most recent first.
select occurred_at, user_label, transcript
from dictation_session_transcripts
order by occurred_at desc
limit 50;
An earlier version of the app stored each final result as its own row in
dictation_transcripts. Nothing writes to that table now. To read what it
holds, joined up by session:
select min(occurred_at) as started, user_label,
string_agg(transcript, ' ' order by sequence) as said
from dictation_transcripts
group by session_id, user_label
order by started desc;
Things to know:
delete from dictation_session_transcripts where occurred_at < now() - interval '30 days';DATABASE_URL, and under npm run dev and npm run preview,
transcripts are discarded unread.A testing label names the browser that dictation was used from, so that your own testing, and that of people you ask to try the app, can be told apart from other visits. It is stored in that browser only, and has no control in the app.
?user=NAME added to the address, for example
https://your-address/?user=Robin. It stays set for later visits without
the parameter. Opening the app with a different name replaces it.?user=PUBLIC.localStorage.getItem("taskmanager.activityUser") shows the label, or null
when none is set.A label is 1 to 20 letters, digits, hyphens or underscores. Anything else is ignored and leaves the current label as it was.
A label in the address applies to that page straight away and takes precedence
over a stored one. It does not depend on the browser being able to save it. If
the browser cannot save it, as in some private browsing modes and browsers
embedded in other apps, the label lasts only for pages opened with it in the
address, so use the full ?user= link each time on such a browser.
Events from a labelled browser are logged with that label as user. All
others are logged with "user":"PUBLIC", which means only that no label was
set in that browser. It does not confirm an unknown visitor: your own phone, a
private window, or any browser where you have not set a label all count as
PUBLIC. A label is a convenience and not proof of who someone is, because
anyone can open the app with any label. Giving someone a link that includes
?user= labels their dictation activity with that name.
Signing in is optional. It shows who is signed in and keeps one private
setting, a preferred name, on the server. Tasks are not linked to accounts:
they stay in the browser under taskmanager.tasks whether or not anyone is
signed in, and signing in or out leaves the tasks, the assignee filter and the
testing label as they were. Sign-in uses
Better Auth, an open-source library, run in the
app's own functions, with its data in Neon Postgres. The interface says
"account", never "user", because the users in this app are the sample
assignees.
/api/auth/sign-in/social
for Google's sign-in address and goes there. The page is left, so it
reloads when it comes back./api/auth/callback/google. Better Auth checks the
result, finds or creates the account, and sets a session cookie. It then
returns to the address the sign-in started from, including any ?user=
testing label. If sign-in fails, it returns there with ?error=, and the
app says that sign-in did not complete and removes the parameter.The profile endpoint, /api/account/profile, decides whose name to read or
change only from the session cookie, and ignores any account named in the
request. Without a valid session it answers 401. Better Auth's other
endpoints, such as the one that would let the browser change the stored name,
are not served.
If sign-in is not configured, or its database does not answer, the app works
as before and the account area says "Sign-in is unavailable".
/api/account/status reports {"configured": true} or false, as the
dictation status does.
Limitation. Where browser storage is blocked, tasks and the filter selection exist only in memory, and the reload that sign-in causes loses them. There is no warning, which was accepted for this demo.
| Table | Contents |
|---|---|
auth_user | Account ID, the Google name and email from the first sign-in, and when it was created. The photo column is always empty. |
auth_account | Google's permanent ID for the account (account_id). The token and scope columns are always empty. |
auth_session | One row per signed-in browser, deleted on sign-out. The IP address and user agent columns are always empty. |
auth_verification | Short-lived state, kept for a few minutes during each sign-in. |
user_profile | The preferred name, 1 to 50 characters, if one is set. |
Database hooks in server/accountAuth.ts empty the token, photo, IP address
and user agent fields before anything is saved. The IP address is still used
in memory to rate-limit sign-in requests. The name and email are not updated
on later sign-ins. The public page /privacy.html says the same for people
signing in, and Google's sign-in screen links to it. Change it if what is
stored changes.
There are two separate sign-in stores, so that development never reads or changes production's accounts:
| Where | Store | Address |
|---|---|---|
| Production | the existing Neon database, DATABASE_URL | BETTER_AUTH_URL |
npm run dev | the Neon project taskmanager-local, AUTH_DATABASE_URL in .env.local | http://localhost:5173 |
Sign-in uses DATABASE_URL only when VERCEL_ENV is production. Locally
it needs AUTH_DATABASE_URL and, without it, reports sign-in as unavailable
rather than falling back. The Vite plugin loads only the sign-in variables from
.env.local, never DATABASE_URL.
Vercel previews have no sign-in and always report it as unavailable, whatever variables they have. Signing in on a preview was dropped because each preview's address changes, and Google allows only listed return addresses.
Never paste a secret into a chat or a ticket. Copy it straight from the
console into .env.local or Vercel.
Google Cloud Console. Ignore any "free trial" banner. Google sign-in needs no billing.
openid, .../auth/userinfo.email and
.../auth/userinfo.profile.https://<production>/api/auth/callback/google
and http://localhost:5173/api/auth/callback/google. Copy the client
secret when it is shown.https://<production>/), privacy policy link
(https://<production>/privacy.html) and authorised domain (the
production host in full, because vercel.app is a public suffix). Then
choose Publish app on the Audience page. With only these scopes and no
logo, Google requires no verification.Second Neon database. In Vercel, under Infrastructure, then Storage,
create a Neon database taskmanager-local. No deployment uses it, so
connect it to no environment, or to Development only if Vercel requires
one. Open it in Neon and copy its connection string. Do not use a branch
of the production database instead: a branch starts as a copy of its
parent, accounts included.
Tables. Run server/accountTables.sql in the Neon SQL Editor for the
production database and for taskmanager-local. It is safe to run
again. The app never creates tables.
Variables. Make each random secret with a command that does not show it. In PowerShell this copies a new one to the clipboard:
$b = New-Object byte[] 32; [Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($b); -join ($b | ForEach-Object { $_.ToString('x2') }) | Set-Clipboard; Remove-Variable b
| Variable | Production | .env.local |
|---|---|---|
GOOGLE_CLIENT_ID | yes | yes |
GOOGLE_CLIENT_SECRET | yes | yes |
Changing BETTER_AUTH_SECRET signs everyone out.
In the Neon SQL Editor, on the store concerned:
-- Every account, with its preferred name and number of signed-in browsers.
select u.id, u.name, u.email, u.created_at, p.preferred_name,
(select count(*) from auth_session s where s.user_id = u.id) as sessions
from auth_user u
left join user_profile p on p.user_id = u.id
order by u.created_at;
-- Confirm that no tokens are kept. Every count should be 0.
select count(access_token), count(refresh_token), count(id_token), count(scope)
from auth_account;
-- Remove one account and everything kept about it: its sessions, its link to
-- Google and its preferred name go with it.
delete from auth_user where email = '[email protected]';
The next sign-in with that Google account creates a new account.
taskmanager-local.better-auth is pinned to an exact version. Upgrade it on its own, check the
release notes for changes to the tables, and run any new table changes in both
stores before deploying.
| Command | Description |
|---|---|
npm run dev | Start the Vite development server. |
npm run dev:browser-check | Start the isolated server that browser checks run against. |
npm run build | Check TypeScript and create a production build in dist/. |
npm run lint | Check the code with ESLint. |
npm test | Run the unit tests once. |
npm run test:watch | Rerun the unit tests as files change. |
npm run preview | Serve the production build locally; run npm run build first. |
Tickets are issues in this project's GitHub repository, and AGENTS.md has the
rules for them. Outside GitHub a ticket is written with the prefix TM, such as
TM #17.
Tickets were files under tickets/ until 2026-10-11. Each of those is now the
issue numbered ten higher, with its old ID in the title: old TM-1 is TM #11.
Claude Code can open the app in a real browser, use it, and report what it saw.
It does this through the
Playwright MCP server, which is
registered for this project in .mcp.json. Nothing is added to package.json:
the server is fetched by npx the first time it is used, and npm install,
npm run dev, npm run build, npm run lint and npm test work the same
without it. AGENTS.md says when Claude runs browser checks and the rules it
follows.
.mcp.json starts @playwright/mcp at exactly version 0.0.83, through the
launcher server/startPlaywrightMcp.mjs:
.mcp.json only overrides the setting it names. An inherited
variable could otherwise load saved cookies
(PLAYWRIGHT_MCP_STORAGE_STATE), attach to a browser that is already
running (PLAYWRIGHT_MCP_CDP_ENDPOINT), or read another configuration or
secrets file (PLAYWRIGHT_MCP_CONFIG, PLAYWRIGHT_MCP_SECRETS_FILE),
whatever --isolated says.PLAYWRIGHT_, PW_, PWTEST_, PWMCP_ or PWDEBUG is set, and names
the variable without showing its value. This includes harmless ones such
as PLAYWRIGHT_BROWSERS_PATH. If /mcp shows playwright as failed,
start Claude Code from a shell without those variables.--isolated keeps the browser profile in memory, so it starts empty, is
discarded when the browser closes, and never touches your own profile.--allowed-origins http://127.0.0.1:5183 limits the browser's requests to
the browser-check server. Playwright MCP documents this as a guardrail and
not a security boundary, and it does not apply to redirects.--block-service-workers stops a page from installing a service worker.--output-dir .playwright-mcp is where screenshots and other files go.
Git ignores that folder.--cdp-endpoint, --extension) or that would allow files outside
the project to be read (--allow-unrestricted-file-access)..claude/settings.json denies the browser_run_code_unsafe tool, which
Playwright MCP describes as equivalent to running arbitrary code on this
computer.npm run dev:browser-check starts a separate server for the checks, using
vite.browser-check.config.ts, at http://127.0.0.1:5183:
.env files, so it never reads the Speechmatics key or the
sign-in settings in .env.local. Dictation and sign-in show as
unavailable.The version was checked against the npm registry on 2026-10-08, when 0.0.83 was the latest release. Each release depends on a pre-release build of Playwright, which is how Microsoft publishes it. There is no stable alternative, so the version is fixed here instead of following the newest release.
.mcp.json when a conversation starts and asks you to approve the
playwright server the first time./mcp and check that playwright shows as connected. The first start
downloads the package, so it can take a little while.Ask Claude to run a browser check of the app. It should start the browser-check
server, open http://127.0.0.1:5183 in a new Chrome window that has none of
your bookmarks or sign-ins, and describe a screenshot of the task list.
While that address is restricted, two things the page normally fetches from elsewhere are blocked: the assignee photos and the Vercel Web Analytics debug script. Missing photos and console messages about those two requests are expected during a browser check.
npm run dev:browser-check as a process that can be stopped on its
own. Confirm that it listens on 127.0.0.1:5183 and that both
GET /api/dictation/status and GET /api/account/status return
{"configured":false}.http://127.0.0.1:5183 in the browser that Playwright MCP provides,
and use "Reset to sample tasks" before the first check.Things to know while checking:
ERR_BLOCKED_BY_CLIENT console errors for
i.pravatar.cc and va.vercel-scripts.com are expected, and their number
varies as tasks are added, reassigned and reloaded. Treat any other console
error or failed request as a finding.yyyy-mm-dd, whatever format the
page displays. A priority slider can be set directly, or by clicking it and
pressing the arrow keys..playwright-mcp/, with
names that say what they show. Playwright MCP also writes a page snapshot and
a console log there on its own. Git ignores the folder..mcp.json, .claude/settings.json, vite.browser-check.config.ts,
server/browserCheckEnvironment.ts and its test,
server/startPlaywrightMcp.mjs, server/playwrightMcpEnvironment.mjs and
its test, the dev:browser-check script in package.json, and the
vite.browser-check.config.ts entry and the allowJs and checkJs options
in tsconfig.node.json..playwright-mcp folder if it exists. Optionally delete
node_modules/.vite-browser-check, the browser-check server's dependency
cache, which is otherwise removed along with node_modules.npx cache,
which is under %LOCALAPPDATA%\npm-cache\_npx on Windows.To switch it off without removing it, reject the playwright server when
Claude Code asks, or run claude mcp reset-project-choices to be asked again.
Codex does not read .mcp.json. It takes MCP servers from ~/.codex/config.toml
or from a project .codex/config.toml, so it would need an equivalent entry
there. That has not been set up.
.codex/rules/validation.rules allows npm test, npm run lint, and
npm run build to run outside the sandbox without repeated approval prompts.
Keep workspace-write sandbox protection and on-request approvals enabled; other
commands needing execution outside the sandbox still require approval.
Trust this project in Codex and restart Codex after adding or changing the rules.
The allowances apply to TaskManager project sessions, not unrelated project sessions. They match command prefixes, including trailing arguments, and do not restrict the working directory of each matching command. They trust the project scripts and their subprocesses. Remove the rules and restart Codex to revoke these allowances; avoid saving them as user-global permissions.
BETTER_AUTH_SECRET |
| its own random value |
| its own random value |
BETTER_AUTH_URL | https://<production> | http://localhost:5173 |
AUTH_DATABASE_URL | not set | taskmanager-local's connection string |
Set the production variables for the Production environment only. Node.js must be 22 or later, because the Neon connection needs a built-in WebSocket.
Redeploy, or restart npm run dev, after changing a variable.
BETTER_AUTH_GOOGLE_OAUTH_PROXY_AUTH_npm run dev, which can stay running.node_modules/.vite-browser-check,
separate from the node_modules/.vite cache that npm run dev uses, so
neither server rebuilds a cache the other is serving from.npm run dev, it never connects to the production database.