Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e15faab
wip: integrate polar and implement billing settings card
Shunseii Feb 28, 2026
8e9cbb7
feat: pencil designs
Shunseii Feb 28, 2026
132404a
feat: add translations
Shunseii Feb 28, 2026
6d6bcff
feat(marketing): add pricing section
Shunseii Feb 28, 2026
a3b82fe
feat(api): handle webhook subscription events by setting plan and sta…
Shunseii Feb 28, 2026
e958ed2
fix(web): small fixes
Shunseii Feb 28, 2026
34eea40
chore: add designs for marketing and updated designs for web
Shunseii Feb 28, 2026
25070b1
fix: invalidate cookie cache on client and server after subscribing
Shunseii Feb 28, 2026
47c318b
wip: start implementing ai autocomplete endpoint
Shunseii Mar 1, 2026
6f14232
fix: dont create polar user on sign up in dev/local env so that sign …
Shunseii Mar 1, 2026
77bda4f
feat: upgrade zod to v4.3 and implement ai autocomplete endpoint
Shunseii Mar 2, 2026
c6bd2f7
wip: first pass ai integration
Shunseii Mar 3, 2026
9bdefa4
feat: implement AI autofill and example generation for dictionary ent…
Shunseii Mar 24, 2026
2541981
chore: apply formatter fixes
Shunseii Mar 24, 2026
86dc940
design: move design files into design directory
Shunseii Mar 28, 2026
0cfbb04
feat: add revlog stats tracking and fix Eden Treaty type inference
Shunseii Mar 28, 2026
431ee30
feat: add OG image meta tags to marketing site
Shunseii Mar 28, 2026
01476b4
chore: fix import ordering
Shunseii Mar 28, 2026
98fcd0c
refactor: migrate clearBacklog to Drizzle ORM
Shunseii Apr 1, 2026
cb831c0
fix: use stemmed token length for Arabic search fuzzy tolerance
Shunseii Apr 1, 2026
876ef11
fix: delete flashcards when deleting a dictionary entry
Shunseii Apr 1, 2026
26f749c
style: lint
Shunseii Apr 1, 2026
2ae52e8
fix: resolve type errors breaking web app build
Shunseii Apr 2, 2026
1955a4d
Merge pull request #39 from Shunseii/feat/revlogs
Shunseii Apr 2, 2026
bf33449
Merge pull request #38 from Shunseii/feat/ai-autcompletion
Shunseii Apr 2, 2026
17b685e
fix: address PR review feedback
Shunseii Apr 2, 2026
a831edd
fix: transaction safety, date validation, and error handling
Shunseii Apr 2, 2026
c44e81e
fix: webhook user validation, Arabic translation, and select a11y
Shunseii Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ expo-env.d.ts
.metro-health-check*

**/.claude/settings.local.json
.claude/skills/socratic-tutor/

# Astro
.astro/
.memelord/
.mcp.json
22 changes: 22 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"languages": {
"TSX": {
"formatter": [{ "language_server": { "name": "biome" } }]
},
"TypeScript": {
"formatter": [{ "language_server": { "name": "biome" } }]
},
"Astro": {
"formatter": [{ "language_server": { "name": "biome" } }]
},
"HTML": {
"formatter": [{ "language_server": { "name": "biome" } }]
},
"JSON": {
"formatter": [{ "language_server": { "name": "biome" } }]
}
},
"code_actions_on_format": {
"source.organizeImports.biome": true
}
}
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ Bahar is an Arabic language learning application built as a monorepo using pnpm
## Getting Started

1. Get the environment variables from Infisical
2. Run `pnpm run dev` and `make local-db`
2. Run `pnpm run dev` and `make local-db`
3. Access the web app at `http://localhost:5173`
4. Access the API at `http://localhost:3000`
5. Access the marketing website at `http://localhost:4321`
6. To run drizzle studio to access the local database, run `pnpm run --filter api drizzle:studio`.
7. If you need to test payments, make sure to set up a Cloudflare Tunnel by reading the instructions [here](./apps/api/README.md#local-development).

## Projects

Expand Down
12 changes: 10 additions & 2 deletions apps/api/.example.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
WEB_CLIENT_DOMAIN="localhost:4000"
NEW_WEB_CLIENT_DOMAIN="localhost:4000"
WEB_CLIENT_DOMAIN="localhost:5173"

PORT=3000
HOST="0.0.0.0"
Expand Down Expand Up @@ -27,3 +26,12 @@ BETTER_AUTH_SECRET=""

SENTRY_DSN=""
SENTRY_ENV=""

POLAR_ACCESS_TOKEN=""
POLAR_WEBHOOK_SECRET=""
POLAR_PRO_PRODUCT_ID=""
POLAR_PRO_ANNUAL_PRODUCT_ID=""

CF_AI_GATEWAY_TOKEN=""
CLOUDFLARE_ACCOUNT_ID=""
CLOUDFLARE_AI_GATEWAY_ID=""
21 changes: 6 additions & 15 deletions apps/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ pnpm install

The API runs on `http://localhost:3000`.

4. For testing Polar payments integration locally, use a Cloudflare Tunnel to expose the API.

See [the docs](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/create-local-tunnel/) to set up Cloudflare Tunnel. Contact an admin to get the tunnel name and config file. You'll need access to Cloudflare.

Once set up, run the tunnel with `cloudflared tunnel run <tunnel-name>`.

### Setting Up a New User (Fresh Local DB)

When working with a fresh local database, you need to manually seed the user database migrations:
Expand All @@ -101,12 +107,10 @@ When working with a fresh local database, you need to manually seed the user dat
4. Create a new user through the web app (sign-up flow)

5. Manually convert the user to an admin in the local database:

- Open Drizzle Studio: `pnpm run --filter api drizzle:studio`
- Find the user in the `users` table and set the role to `admin`

6. Seed the user database migrations:

- Copy the migration SQL from `packages/drizzle-user-db-schemas/drizzle/*.sql`
- Remove the `--> statement-breakpoint` markers and replace with newlines
- Manually insert records into the `migrations` table in the user's database
Expand Down Expand Up @@ -193,16 +197,3 @@ docker run --network host -p 3000:3000 --env-file apps/api/.env bahar-api
## Running in Production

The Docker container runs the compiled `server` binary. Migrations run automatically via Fly.io's `release_command` before deployment.

## Environment Variables

Required environment variables:

- `DATABASE_URL` - Turso central database URL
- `DATABASE_AUTH_TOKEN` - Turso auth token
- `TURSO_API_TOKEN` - Turso API token for per-user database management
- `TURSO_ORGANIZATION` - Turso organization slug
- `BETTER_AUTH_SECRET` - Secret for Better Auth
- `REDIS_URL` - Upstash Redis URL
- `REDIS_TOKEN` - Upstash Redis token
- `SENTRY_DSN` - Sentry DSN for error tracking
2 changes: 2 additions & 0 deletions apps/api/drizzle/0013_damp_scarecrow.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE `users` ADD `plan` text;--> statement-breakpoint
ALTER TABLE `users` ADD `subscriptionStatus` text;
17 changes: 17 additions & 0 deletions apps/api/drizzle/0014_omniscient_rumiko_fujikawa.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
CREATE TABLE `revlogs` (
`id` text PRIMARY KEY NOT NULL,
`user_id` text NOT NULL,
`difficulty` real DEFAULT 0,
`due` text NOT NULL,
`due_timestamp_ms` integer NOT NULL,
`review` text NOT NULL,
`review_timestamp_ms` integer NOT NULL,
`learning_steps` integer DEFAULT 0,
`scheduled_days` integer DEFAULT 0,
`stability` real DEFAULT 0,
`state` integer DEFAULT 0,
`direction` text DEFAULT 'forward' NOT NULL,
`source` text DEFAULT 'review' NOT NULL,
`created_at` integer DEFAULT (unixepoch()) NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
);
Loading