Dosu web app#
Handles self-serve setup and repository config for the Dosu GitHub bot.
Current stack:
- pnpm
- Supabase
- NextJS
- shadcn
- Tailwind
- Lucide icons
- Vitest (unit tests)
- Cypress (E2E tests)
Installation#
Ensure you have nvm and pnpm installed. After cloning the repository, run
$ nvm use # Switch to the node version specified in .nvmrc
$ pnpm install
We're using Stripe Webhooks to handle events from Stripe.
- Install Stripe CLI
- Ask the Team to invite you to the Stripe account.
Setup Environment Variables#
In the /frontend/app directory, run the following commands:
$ vercel login
$ npm run pull-vercel-env # This scripts will pull the environment variables(dev/test/prod) from Vercel
Getting started#
Start Docker and Supabase, see /supabase directory.
$ pnpm run dev
Run in production environment#
Please ensure that you run the app on 3001 port, because the auth flow is only configured for this port.
$ pnpm run dev:prod
Run with HTTPS for local subdomain development#
To test custom subdomain functionality locally (e.g., ask-cncf.dosu-local.dev), you need to run the app with HTTPS. This enables:
- Testing subdomain routing and middleware logic
- Cross-subdomain cookie sharing (authentication state shared between
localhostand*.dosu-local.dev) - Proper SSL certificate validation
Prerequisites:
-
Install
mkcertfor SSL certificates:brew install mkcert mkcert -install -
Generate SSL certificates (macOS/Linux):
cd frontend/app chmod +x ./scripts/generate-local-certs.sh # first run only sudo ./scripts/generate-local-certs.sh -
Configure DNS for
*.dosu-local.dev:
Use dnsmasq
Run the setup script:cd frontend/app ./scripts/setup-dns.sh -
Start the HTTPS development server using Next.js official HTTPS support (listening on port 443). The script automatically spins up the Stripe webhook helper with the correct forwarding target:
sudo pnpm run dev:httpsPort 443 requires elevated privileges on macOS/Linux, so you'll be prompted for your password unless you've already granted Node the appropriate capabilities. The script relies on Next.js'
--experimental-httpsflag and the certificates generated above. -
Access your application:
https://ask-cncf.dosu-local.dev(maps to the configured public space ID)https://ask.cncf-local.iohttps://dosu-local.devhttps://localhost
Important Notes:
- Authentication cookies are shared across
*.dosu-local.devsubdomains when using HTTPS localhostand*.dosu-local.devcannot share cookies due to browser security (different origins)- If DNS doesn't resolve, restart your browser after configuration
- See
frontend/app/certs/README.mdfor detailed troubleshooting - Custom domain mappings (e.g.,
ask-cncf) live infrontend/packages/core/src/config/domain-config.ts.
Troubleshooting:
If you encounter DNS resolution issues:
# Check dnsmasq status
brew services list | grep dnsmasq
# Test DNS
dig @127.0.0.1 ask-cncf.dosu-local.dev +short
# Flush DNS cache
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
Supabase#
Migrations#
Apply the latest migrations locally:
$ supabase migration up
Check local DB changes against branch:
$ supabase db diff
Reset DB and repopulate from seed.sql file:
Reset DB#
To reset the database and load the test data from supabase/seed.sql run
$ supabase db reset
Emails#
Emails are sent via react-email, you can get a testing UI on port 3005 with
$ pnpm email
Testing#
*Please ensure that you have installed the Chrome browser.
To run the Unit tests:
$ pnpm test:unit # Run the unit tests in watch mode
$ pnpm test:unit:ci # Run the unit tests once
To run the E2E tests in development mode:
$ pnpm test:e2e
To run the E2E tests in CI mode:
$ pnpm build:test
$ pnpm test:e2e:ci
How to write tests:
- Start the test runner in watch mode
- extensions
- E2E tests ->
*.cy.ts - Unit tests ->
*.spec.ts
- E2E tests ->
- Create a new test file near the component/page you want to test (e.g.
app/login/page.cy.tsorutils/utils.spec.ts). - Write your test and ensure it passes before committing. Here are some examples:
- Cypress E2E test
- Vitest Unit test
Nango Integration (Local Development)#
When developing features that involve Nango OAuth integrations (Notion, Confluence, GitLab, Coda), you need to configure your own Nango integration to avoid webhook conflicts with other developers.
Setup Steps#
-
Create your personal integrations in Nango Dashboard
For each provider you need, create an integration with your name suffix:
notion-{yourname}(e.g.,notion-caspian)confluence-{yourname}- Copy OAuth credentials from the production integration
-
Configure local environment variable
# Append to frontend/app/.env.development.local NEXT_PUBLIC_NANGO_SUFFIX=yourname -
Set up webhook forwarding
Ask a team admin to add your tailscale URL to
WEBHOOK_FORWARD_TARGETS:yourname=https://your-machine.tailnet-name.ts.net:3001/api/public/oauth/nango/webhook
How It Works#
| Environment | NEXT_PUBLIC_NANGO_SUFFIX | Integration ID |
|---|---|---|
| Production | (not set) | notion |
| Staging | staging | notion-staging |
| Local Dev | yourname | notion-yourname |
The webhook router (/api/webhook/nango-dev) extracts the suffix from providerConfigKey and forwards to the matching target URL only.
Development#
Types#
Types from our DB are auto-generated via
$ pnpm gentypes
and stored in /types/supabase.auto.ts. DO NOT modify this file by hand! To add additional DB types use the /types/supabase.ts file, where we merge the auto-generated types with custom types.
Naming conventions#
- Types that correspond to DB tables should have no prefix and the name should be identical to the DB table, e.g.
Org. For nested types via Supabase views the type for the table can be prefixed with a_and the table name can be used for the nested type, e.g._Deployment(table type) andDeployment(nested type). - Types that come from other integrations HAVE TO be prefixed, e.g. all Octokit types have a Github prefix to indicate that those are external and not from our DB. This is to distinguish for example Github Threads and Threads in Supabase. In this case the type for our DB Thread would be
Threadand the type for the Github Thread would beGithubThread. - Types related to layout and UI should be prefixed with
App, e.g.AppBreadcrumbto indicate that those are not related to data, but just helpers. This only applies to types that are exported for reuse, local types do not need a prefix.
Examples#
- demo-nextjs-with-supabase.vercel.app
- Next.js Subscription Payments Starter
- Cookie-based Auth and the Next.js 13 App Router (free course)
- Supabase Auth and the Next.js App Router
VS Code#
If you are opening the project from the root folder, you have to add the following to your workspace
settings to make the i18n-ally extension work.
{
"i18n-ally.enabledFrameworks": ["react"],
"i18n-ally.localesPaths": "./frontend/app/messages"
}
Troubleshooting#
Something doesn't work without any reason#
Most likely this is caused by Supabase. First try supabase stop and supabase start to restart the local Supabase instance. If that doesn't help, try to reset the database with supabase db reset, and if that doesn't help, delete all Docker containers and reinstall them with supabase start.
Generate schema throws errors with ruff and black#
Go to the /backend directory and install the backend hooks with
$ git config --unset-all core.hooksPath && poetry run pre-commit install
Go to the root directory and generate the schema with
$ ./scripts/generate-schemas.sh
Commit via the command line (VS Code seems to not trigger the hooks via git UI).
Error from the Supabase schemas doesn't match#
Error: The schema must be one of the following: public, storage, graphql_public...
When you have updated the api.schemas field in dosu/supabase/config.toml file, you also need to update the configuration in the Data API Settings > Exposed schemas section in the Supabase console online. (staging / production).
Schema errors in CI#
Relink database (to production):
supabase link
Restart supabase:
supabase stop --no-backup && supabase start
Stripe webhook key expired error#
Error message like test key rktest... is expired.
A simple stripe login should fix it.
Backend types not matching schema#
Go to /backend and run
make sqlc-generate
to regenerate sqlc types.
Supabase realtime doesn't connect#
Change the Supabase URLs in .env files from localhost to 127.0.0.1 like
NEXT_PUBLIC_SUPABASE_URL="http://127.0.0.1:54321"
NEXT_PUBLIC_SUPABASE_WS_URL="ws://127.0.0.1:54321"
Safari renders flexbox elements in dialogs with height 0px#
It seems like Safari has problems with h-fit, we need to use h-content instead.
Infinite loop with observers when opening document#
This was caused by upgrading @.../ssr from 0.5.2 to 0.6.1 and @.../supabase-js from 2.49.1 to 2.49.10