Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
93 changes: 42 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,45 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default tseslint.config({
extends: [
// Remove ...tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,
],
languageOptions: {
// other options...
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
},
});
# Welcome to your Convex + React (Vite) + Convex Auth app

This is a [Convex](https://convex.dev/) project created with [`npm create convex`](https://www.npmjs.com/package/create-convex).

After the initial setup (<2 minutes) you'll have a working full-stack app using:

- Convex as your backend (database, server logic)
- [React](https://react.dev/) as your frontend (web page interactivity)
- [Vite](https://vitest.dev/) for optimized web hosting
- [Tailwind](https://tailwindcss.com/) for building great looking UI
- [Convex Auth](https://labs.convex.dev/auth) for authentication

## Get started

If you just cloned this codebase and didn't use `npm create convex`, run:

```
npm install
npm run dev
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from "eslint-plugin-react-x";
import reactDom from "eslint-plugin-react-dom";

export default tseslint.config({
plugins: {
// Add the react-x and react-dom plugins
"react-x": reactX,
"react-dom": reactDom,
},
rules: {
// other rules...
// Enable its recommended typescript rules
...reactX.configs["recommended-typescript"].rules,
...reactDom.configs.recommended.rules,
},
});
If you're reading this README on GitHub and want to use this template, run:

```
npm create convex@latest -- -t react-vite-convexauth
```

For more information on how to configure Convex Auth, check out the [Convex Auth docs](https://labs.convex.dev/auth/).

For more examples of different Convex Auth flows, check out this [example repo](https://www.convex.dev/templates/convex-auth).

## Learn more

To learn more about developing your project with Convex, check out:

- The [Tour of Convex](https://docs.convex.dev/get-started) for a thorough introduction to Convex principles.
- The rest of [Convex docs](https://docs.convex.dev/) to learn about all Convex features.
- [Stack](https://stack.convex.dev/) for in-depth articles on advanced topics.

## Join the community

Join thousands of developers building full-stack apps with Convex:

- Join the [Convex Discord community](https://convex.dev/community) to get help in real-time.
- Follow [Convex on GitHub](https://github.com/get-convex/), star and contribute to the open-source implementation of Convex.
9 changes: 8 additions & 1 deletion convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import type {
FilterApi,
FunctionReference,
} from "convex/server";
import type * as auth from "../auth.js";
import type * as http from "../http.js";
import type * as myFunctions from "../myFunctions.js";

/**
* A utility for referencing Convex functions in your app's API.
Expand All @@ -22,7 +25,11 @@ import type {
* const myFunctionReference = api.myModule.myFunction;
* ```
*/
declare const fullApi: ApiFromModules<{}>;
declare const fullApi: ApiFromModules<{
auth: typeof auth;
http: typeof http;
myFunctions: typeof myFunctions;
}>;
export declare const api: FilterApi<
typeof fullApi,
FunctionReference<any, "public">
Expand Down
34 changes: 18 additions & 16 deletions convex/_generated/dataModel.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@
* @module
*/

import { AnyDataModel } from "convex/server";
import type {
DataModelFromSchemaDefinition,
DocumentByName,
TableNamesInDataModel,
SystemTableNames,
} from "convex/server";
import type { GenericId } from "convex/values";

/**
* No `schema.ts` file found!
*
* This generated code has permissive types like `Doc = any` because
* Convex doesn't know your schema. If you'd like more type safety, see
* https://docs.convex.dev/using/schemas for instructions on how to add a
* schema file.
*
* After you change a schema, rerun codegen with `npx convex dev`.
*/
import schema from "../schema.js";

/**
* The names of all of your Convex tables.
*/
export type TableNames = string;
export type TableNames = TableNamesInDataModel<DataModel>;

/**
* The type of a document stored in Convex.
*
* @typeParam TableName - A string literal type of the table name (like "users").
*/
export type Doc = any;
export type Doc<TableName extends TableNames> = DocumentByName<
DataModel,
TableName
>;

/**
* An identifier for a document in Convex.
Expand All @@ -42,8 +42,10 @@ export type Doc = any;
*
* IDs are just strings at runtime, but this type can be used to distinguish them from other
* strings when type checking.
*
* @typeParam TableName - A string literal type of the table name (like "users").
*/
export type Id<TableName extends TableNames = TableNames> =
export type Id<TableName extends TableNames | SystemTableNames> =
GenericId<TableName>;

/**
Expand All @@ -55,4 +57,4 @@ export type Id<TableName extends TableNames = TableNames> =
* This type is used to parameterize methods like `queryGeneric` and
* `mutationGeneric` to make them type-safe.
*/
export type DataModel = AnyDataModel;
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;
8 changes: 8 additions & 0 deletions convex/auth.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: "convex",
},
],
};
6 changes: 6 additions & 0 deletions convex/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { convexAuth } from "@convex-dev/auth/server";
import { Password } from "@convex-dev/auth/providers/Password";

export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
providers: [Password],
});
8 changes: 8 additions & 0 deletions convex/http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { httpRouter } from "convex/server";
import { auth } from "./auth";

const http = httpRouter();

auth.addHttpRoutes(http);

export default http;
81 changes: 81 additions & 0 deletions convex/myFunctions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { v } from "convex/values";
import { query, mutation, action } from "./_generated/server";
import { api } from "./_generated/api";
import { getAuthUserId } from "@convex-dev/auth/server";

// Write your Convex functions in any file inside this directory (`convex`).
// See https://docs.convex.dev/functions for more.

// You can read data from the database via a query:
export const listNumbers = query({
// Validators for arguments.
args: {
count: v.number(),
},

// Query implementation.
handler: async (ctx, args) => {
//// Read the database as many times as you need here.
//// See https://docs.convex.dev/database/reading-data.
const numbers = await ctx.db
.query("numbers")
// Ordered by _creationTime, return most recent
.order("desc")
.take(args.count);
const userId = await getAuthUserId(ctx);
const user = userId === null ? null : await ctx.db.get(userId);
return {
viewer: user?.email ?? null,
numbers: numbers.reverse().map((number) => number.value),
};
},
});

// You can write data to the database via a mutation:
export const addNumber = mutation({
// Validators for arguments.
args: {
value: v.number(),
},

// Mutation implementation.
handler: async (ctx, args) => {
//// Insert or modify documents in the database here.
//// Mutations can also read from the database like queries.
//// See https://docs.convex.dev/database/writing-data.

const id = await ctx.db.insert("numbers", { value: args.value });

console.log("Added new document with id:", id);
// Optionally, return a value from your mutation.
// return id;
},
});

// You can fetch data from and send data to third-party APIs via an action:
export const myAction = action({
// Validators for arguments.
args: {
first: v.number(),
second: v.string(),
},

// Action implementation.
handler: async (ctx, args) => {
//// Use the browser-like `fetch` API to send HTTP requests.
//// See https://docs.convex.dev/functions/actions#calling-third-party-apis-and-using-npm-packages.
// const response = await ctx.fetch("https://api.thirdpartyservice.com");
// const data = await response.json();

//// Query data by running Convex queries.
const data = await ctx.runQuery(api.myFunctions.listNumbers, {
count: 10,
});
console.log(data);

//// Write data by running Convex mutations.
await ctx.runMutation(api.myFunctions.addNumber, {
value: args.first,
});
},
});
13 changes: 13 additions & 0 deletions convex/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";

// The schema is normally optional, but Convex Auth
// requires indexes defined on `authTables`.
// The schema provides more precise TypeScript types.
export default defineSchema({
...authTables,
numbers: defineTable({
value: v.number(),
}),
});
51 changes: 48 additions & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,31 @@ import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
ignores: [
"dist",
"eslint.config.js",
"convex/_generated",
"postcss.config.js",
"tailwind.config.js",
"vite.config.ts",
],
},
{
extends: [
js.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
globals: {
...globals.browser,
...globals.node,
},
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
},
},
plugins: {
"react-hooks": reactHooks,
Expand All @@ -23,6 +41,33 @@ export default tseslint.config(
"warn",
{ allowConstantExport: true },
],
// All of these overrides ease getting into
// TypeScript, and can be removed for stricter
// linting down the line.

// Only warn on unused variables, and ignore variables starting with `_`
"@typescript-eslint/no-unused-vars": [
"warn",
{ varsIgnorePattern: "^_", argsIgnorePattern: "^_" },
],

// Allow escaping the compiler
"@typescript-eslint/ban-ts-comment": "error",

// Allow explicit `any`s
"@typescript-eslint/no-explicit-any": "off",

// START: Allow implicit `any`s
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "off",
// END: Allow implicit `any`s

// Allow async functions without await
// for consistency (esp. Convex `handler`s)
"@typescript-eslint/require-await": "off",
},
},
);
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/convex.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/src/index.css" />
<title>Vite + React + TS</title>
</head>
<body>
Expand Down
Loading