app OpenSaaS { wasp: { version: "^0.15.0" }, title: "My Open SaaS App", head: [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", // TODO: You can put your Plausible analytics scripts below (https://docs.opensaas.sh/guides/analytics/): // NOTE: Plausible does not use Cookies, so you can simply add the scripts here. // Google, on the other hand, does, so you must instead add the script dynamically // via the Cookie Consent component after the user clicks the "Accept" cookies button. "", // for production "", // for development ], // 🔐 Auth out of the box! https://wasp-lang.dev/docs/auth/overview auth: { userEntity: User, methods: { // NOTE: If you decide to not use email auth, make sure to also delete the related routes and pages below. // (RequestPasswordReset(Route|Page), PasswordReset(Route|Page), EmailVerification(Route|Page)) email: { fromField: { name: "Open SaaS App", email: "me@example.com" }, emailVerification: { clientRoute: EmailVerificationRoute, getEmailContentFn: import { getVerificationEmailContent } from "@src/auth/email-and-pass/emails", }, passwordReset: { clientRoute: PasswordResetRoute, getEmailContentFn: import { getPasswordResetEmailContent } from "@src/auth/email-and-pass/emails", }, userSignupFields: import { getEmailUserFields } from "@src/auth/userSignupFields", }, // Uncomment to enable Google Auth (check https://wasp-lang.dev/docs/auth/social-auth/google for setup instructions): // google: { // Guide for setting up Auth via Google // userSignupFields: import { getGoogleUserFields } from "@src/auth/userSignupFields", // configFn: import { getGoogleAuthConfig } from "@src/auth/userSignupFields", // }, // Uncomment to enable GitHub Auth (check https://wasp-lang.dev/docs/auth/social-auth/github for setup instructions): // gitHub: { // userSignupFields: import { getGitHubUserFields } from "@src/auth/userSignupFields", // configFn: import { getGitHubAuthConfig } from "@src/auth/userSignupFields", // }, // Uncomment to enable Discord Auth (check https://wasp-lang.dev/docs/auth/social-auth/discord for setup instructions): // discord: { // userSignupFields: import { getDiscordUserFields } from "@src/auth/userSignupFields", // configFn: import { getDiscordAuthConfig } from "@src/auth/userSignupFields" // } }, onAfterSignup: import { onAfterSignup } from "@src/auth/hooks", onAuthFailedRedirectTo: "/login", onAuthSucceededRedirectTo: "/demo-app", }, db: { // Run `wasp db seed` to seed the database with the seed functions below: seeds: [ // Populates the database with a bunch of fake users to work with during development. import { seedMockUsers } from "@src/server/scripts/dbSeeds", ] }, client: { rootComponent: import App from "@src/client/App", }, emailSender: { // NOTE: "Dummy" provider is just for local development purposes. // Make sure to check the server logs for the email confirmation url (it will not be sent to an address)! // Once you are ready for production, switch to e.g. "SendGrid" or "Mailgun" providers. Check out https://docs.opensaas.sh/guides/email-sending/ . provider: Dummy, defaultFrom: { name: "Open SaaS App", // When using a real provider, e.g. SendGrid, you must use the same email address that you configured your account to send out emails with! email: "me@example.com" }, }, } route LandingPageRoute { path: "/", to: LandingPage } page LandingPage { component: import LandingPage from "@src/landing-page/LandingPage" } //#region Auth Pages route LoginRoute { path: "/login", to: LoginPage } page LoginPage { component: import Login from "@src/auth/LoginPage" } route SignupRoute { path: "/signup", to: SignupPage } page SignupPage { component: import { Signup } from "@src/auth/SignupPage" } route RequestPasswordResetRoute { path: "/request-password-reset", to: RequestPasswordResetPage } page RequestPasswordResetPage { component: import { RequestPasswordResetPage } from "@src/auth/email-and-pass/RequestPasswordResetPage", } route PasswordResetRoute { path: "/password-reset", to: PasswordResetPage } page PasswordResetPage { component: import { PasswordResetPage } from "@src/auth/email-and-pass/PasswordResetPage", } route EmailVerificationRoute { path: "/email-verification", to: EmailVerificationPage } page EmailVerificationPage { component: import { EmailVerificationPage } from "@src/auth/email-and-pass/EmailVerificationPage", } //#endregion //#region User route AccountRoute { path: "/account", to: AccountPage } page AccountPage { authRequired: true, component: import Account from "@src/user/AccountPage" } query getPaginatedUsers { fn: import { getPaginatedUsers } from "@src/user/operations", entities: [User] } action updateCurrentUser { fn: import { updateCurrentUser } from "@src/user/operations", entities: [User] } action updateUserById { fn: import { updateUserById } from "@src/user/operations", entities: [User] } //#endregion //#region Demo AI App route DemoAppRoute { path: "/demo-app", to: DemoAppPage } page DemoAppPage { authRequired: true, component: import DemoAppPage from "@src/demo-ai-app/DemoAppPage" } action generateGptResponse { fn: import { generateGptResponse } from "@src/demo-ai-app/operations", entities: [User, Task, GptResponse] } action createTask { fn: import { createTask } from "@src/demo-ai-app/operations", entities: [Task] } action deleteTask { fn: import { deleteTask } from "@src/demo-ai-app/operations", entities: [Task] } action updateTask { fn: import { updateTask } from "@src/demo-ai-app/operations", entities: [Task] } query getGptResponses { fn: import { getGptResponses } from "@src/demo-ai-app/operations", entities: [User, GptResponse] } query getAllTasksByUser { fn: import { getAllTasksByUser } from "@src/demo-ai-app/operations", entities: [Task] } //#endregion //#region Payment route PricingPageRoute { path: "/pricing", to: PricingPage } page PricingPage { component: import PricingPage from "@src/payment/PricingPage" } route CheckoutRoute { path: "/checkout", to: CheckoutPage } page CheckoutPage { authRequired: true, component: import Checkout from "@src/payment/CheckoutPage" } query getCustomerPortalUrl { fn: import { getCustomerPortalUrl } from "@src/payment/operations", entities: [User] } action generateCheckoutSession { fn: import { generateCheckoutSession } from "@src/payment/operations", entities: [User] } api paymentsWebhook { fn: import { paymentsWebhook } from "@src/payment/webhook", entities: [User], middlewareConfigFn: import { paymentsMiddlewareConfigFn } from "@src/payment/webhook", httpRoute: (POST, "/payments-webhook") } //#endregion //#region File Upload route FileUploadRoute { path: "/file-upload", to: FileUploadPage } page FileUploadPage { authRequired: true, component: import FileUpload from "@src/file-upload/FileUploadPage" } action createFile { fn: import { createFile } from "@src/file-upload/operations", entities: [User, File] } query getAllFilesByUser { fn: import { getAllFilesByUser } from "@src/file-upload/operations", entities: [User, File] } query getDownloadFileSignedURL { fn: import { getDownloadFileSignedURL } from "@src/file-upload/operations", entities: [User, File] } //#endregion //#region Analytics query getDailyStats { fn: import { getDailyStats } from "@src/analytics/operations", entities: [User, DailyStats] } job dailyStatsJob { executor: PgBoss, perform: { fn: import { calculateDailyStats } from "@src/analytics/stats" }, schedule: { cron: "0 * * * *" // every hour. useful in production // cron: "* * * * *" // every minute. useful for debugging }, entities: [User, DailyStats, Logs, PageViewSource] } //#endregion //#region Admin Dashboard route AdminRoute { path: "/admin", to: AnalyticsDashboardPage } page AnalyticsDashboardPage { authRequired: true, component: import AnalyticsDashboardPage from "@src/admin/dashboards/analytics/AnalyticsDashboardPage" } route AdminUsersRoute { path: "/admin/users", to: AdminUsersPage } page AdminUsersPage { authRequired: true, component: import AdminUsers from "@src/admin/dashboards/users/UsersDashboardPage" } route AdminSettingsRoute { path: "/admin/settings", to: AdminSettingsPage } page AdminSettingsPage { authRequired: true, component: import AdminSettings from "@src/admin/elements/settings/SettingsPage" } route AdminChartsRoute { path: "/admin/chart", to: AdminChartsPage } page AdminChartsPage { authRequired: true, component: import AdminCharts from "@src/admin/elements/charts/ChartsPage" } route AdminFormElementsRoute { path: "/admin/forms/form-elements", to: AdminFormElementsPage } page AdminFormElementsPage { authRequired: true, component: import AdminForms from "@src/admin/elements/forms/FormElementsPage" } route AdminFormLayoutsRoute { path: "/admin/forms/form-layouts", to: AdminFormLayoutsPage } page AdminFormLayoutsPage { authRequired: true, component: import AdminForms from "@src/admin/elements/forms/FormLayoutsPage" } route AdminCalendarRoute { path: "/admin/calendar", to: AdminCalendarPage } page AdminCalendarPage { authRequired: true, component: import AdminCalendar from "@src/admin/elements/calendar/CalendarPage" } route AdminUIAlertsRoute { path: "/admin/ui/alerts", to: AdminUIAlertsPage } page AdminUIAlertsPage { authRequired: true, component: import AdminUI from "@src/admin/elements/ui-elements/AlertsPage" } route AdminUIButtonsRoute { path: "/admin/ui/buttons", to: AdminUIButtonsPage } page AdminUIButtonsPage { authRequired: true, component: import AdminUI from "@src/admin/elements/ui-elements/ButtonsPage" } route NotFoundRoute { path: "*", to: NotFoundPage } page NotFoundPage { component: import { NotFoundPage } from "@src/client/components/NotFoundPage" } //#endregion //#region Contact Form Messages // TODO: // add functionality to allow users to send messages to admin // and make them accessible via the admin dashboard route AdminMessagesRoute { path: "/admin/messages", to: AdminMessagesPage } page AdminMessagesPage { authRequired: true, component: import AdminMessages from "@src/messages/MessagesPage" } //#endregion //#region Newsletter job sendNewsletter { executor: PgBoss, perform: { fn: import { checkAndQueueNewsletterEmails } from "@src/newsletter/sendNewsletter" }, schedule: { cron: "0 7 * * 1" // at 7:00 am every Monday }, entities: [User] } //#endregion