feat: add Home page with user dashboard and habit tracking features

- Implemented Home component with user authentication and loading states.
- Created Welcome component for unauthenticated users with a sign-in option.
- Developed Dashboard component to display user's habits and progress.
- Added functionality for habit management, including adding, updating, and deleting habits.
- Integrated HabitChart and HabitHistory components for visual representation of habits.
- Introduced sharing functionality for progress via Discord integration.

feat: establish Discord sharing configuration and routes

- Added DiscordSharingConfig type and readDiscordSharingConfig function for environment variable management.
- Created sharing contracts for input validation and data structure.
- Implemented sharing routes for previewing and sending progress images to Discord.
- Added tests for sharing routes to ensure authentication and proper error handling.
This commit is contained in:
syntaxbullet
2026-09-04 17:48:54 +02:00
parent dde5e77317
commit ecc2620a4c
34 changed files with 4017 additions and 140 deletions

View File

@@ -1,7 +1,7 @@
# Minabot
Bun + Hono habit-tracking REST API with Drizzle ORM and local SQLite. The existing
React Router client currently contains only the design system, ready for a fresh page redesign.
Bun + Hono habit-tracking REST API with Drizzle ORM and local SQLite. The React Router
client includes a homepage for signed-out visitors and a personal habit dashboard.
See [the REST API reference](docs/API.md) for habits, task recurrence, dated progress,
combined calendars, historical corrections, daily resets, and optional count carryover.
@@ -13,7 +13,10 @@ bun dev
Open http://127.0.0.1:3000. Set `PORT` to use a different port.
- Client page: `/design-system`. Root and all other client URLs redirect there.
- Homepage: `/`. Signed-out visitors see an introduction and interactive examples;
signed-in users see their saved habits and todays progress.
- Component library: `/design-system`, independent of account loading.
- Unknown client URLs redirect to `/`.
- Hono endpoint: `GET /api/health`.
- Unknown API routes return JSON with a 404 status.
@@ -43,10 +46,36 @@ The Playground, Editing, and References showcase tabs have been removed.
Reusable calendar, editing, color-picker components and reference assets remain
available for future pages.
The previous Landing, Home, About, and Settings pages have been removed. The
backend API, authentication infrastructure, database, and reusable components remain
available for the redesigned pages. The design system does not load account data
or call the API.
The homepage is composed from the existing design-system components and layouts:
shared page shell, WelcomePanel, Card/CardGrid, SectionHeading, HabitChart, CalendarHeatmap,
Counter, Checkbox, Field, ScheduleEditor, HabitColorPicker, and DiscordSignInButton.
It uses no page-specific styles. The shared page shell also renders the component
library. The design system does not load account data or call the API.
The dashboard's welcome panel groups the Discord avatar, greeting, progress, and
habit actions on the left, with the account's current date and timezone on the
right. It stacks on narrow screens and shows an initial if the avatar is unavailable.
Signed-in users can create manual, count, or task habits, choose a recurrence and
color, log todays progress, and inspect their real calendars. Completed-versus-due
counts exclude days off. Inline controls beside habit headings edit the name,
tracking method, schedule, color, count target/unit, and unfinished-count carryover.
Each task can be renamed, rescheduled, or deleted in place; Add task also supports
its own recurrence. Both habit and task schedules support daily, selected weekdays,
day intervals, and week intervals with an editable start date and weekday.
Delete asks for confirmation in place and preserves earlier history. Tasks
remain manageable on days off, while their checkboxes stay disabled.
Mutations are saved through the authenticated API; failed
saves retain the recorded values and allow retry. Account and calendar failures
have retry states. The dashboard refreshes on window focus and every minute while
visible, using the servers date and saved account timezone. Historical editing
and combined-chart management are not exposed on this homepage.
For browser QA without changing application data, run
`bun scripts/dashboard-preview.ts` and visit
`http://127.0.0.1:3107/__preview/login`. This uses an in-memory database and a
separate preview cookie. The signed-out examples use a fixed September 4, 2026
demo date; progress in those examples is never saved.
`styles/globals.css` is the only stylesheet
entry point; component styles are in Tailwind's components layer so utilities can
@@ -131,8 +160,8 @@ Import `db` from `src/db/index.ts` in backend code to query the database.
Use the matching hostname throughout each sign-in; `localhost` and `127.0.0.1`
have different cookie storage.
5. Run `bun dev`, click **Sign in with Discord**, and authorize the `identify` scope.
No bot token or email scope is needed. After returning, **View my profile** opens
`/api/me`. **Sign out** revokes the current browser's session.
No bot token or email scope is needed. After returning, the homepage opens your
habit dashboard. **Sign out** revokes the current browser's session.
Without the OAuth settings, public pages and `/api/health` remain usable, `/api/me`
returns 401, and sign-in displays a configuration message. Restart after editing
@@ -191,6 +220,41 @@ production habit data separate from development data.
remain UTC and daily boundaries follow the saved timezone with preserved historical
deadlines. See the API reference for travel and DST behavior.
### Progress sharing
Use **Share progress** on the dashboard to select up to six habits and a 7-day,
30-day, yearly, or custom range (at most 366 days, ending no later than today).
The preview, PNG download, and Discord attachment use the same 1200px-wide image.
Each habit has a color legend; completion rates exclude unscheduled days. Display
name, avatar, habit names, and timezone can be hidden separately. Task names are
never included. PNGs are rendered locally in the browser and are not stored by
the server.
Set `DISCORD_BOT_TOKEN` and `DISCORD_SHARING_CHANNEL_ID` in `.env` (or the selected
environment file), then restart the server. Invite the bot to the Discord server
and grant it View Channel, Send Messages, and Attach Files in the sharing channel.
Threads additionally require Send Messages in Threads. The app displays the
configured destination automatically; all signed-in users share to that channel.
**Send to Discord** posts only the previewed PNG as the bot, with mentions disabled.
The bot token stays in the server environment and is never stored in SQLite or
returned to the browser. No Gateway connection or message-content intent is needed.
Delivery IDs and Discord message nonces protect against duplicate posts; ambiguous
network failures ask the user to check the channel. Webhook setup has been retired,
and the migration removes saved webhook connections while retaining delivery history.
The authenticated `/api/sharing` routes require the configured Origin for mutations:
| Method | Route | Behavior |
| --- | --- | --- |
| POST | `/preview` | `{habitIds, from, to}` → owned calendar data, totals, and legends |
| GET | `/discord` | Bot sharing status, channel name, and channel link; no credentials |
| POST | `/discord/send` | Multipart `image` PNG (up to 4 MB) and UUID `deliveryId` |
For isolated browser QA, `SHARE_PREVIEW=1 bun scripts/dashboard-preview.ts` creates
sample history and a local Discord transport stub on port 3107. Its login route
is `/__preview/login`; `/__preview/shared-image` returns the last attachment for
inspection. This mode never contacts Discord or opens the application database.
### API
| Method | Route | Behavior |