# Project export: BulkQR

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Make & Customize QR Codes in Bulk
- Devpost: https://devpost.com/software/bulkqr
- GitHub: https://github.com/kkapadia10/TreeHacks
- Video: https://www.youtube.com/embed/_M0FCvT7aOg?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Kaden Kapadia (2 commits)

## Devpost submission (written by the team)

### Inspiration

As avid Canva fans, we noticed that when we needed to make QR codes in bulk, the native features were often cumbersome. Having to independently click to form each QR code would waste a lot of time.

### What it does

Our app allows users to upload a list of QR codes and generate QR in bulk, thus saving users a lot of time. We also created a feature where users can choose the theme of the QR codes, allowing them to customize the aesthetics of the QR codes according to a theme, like rainbow or black/white.

### How we built it

We used the native Canva developer toolkit, and we simply built additional buttons on top of it. We used React Native as our tech stack, which integrates into Canva. We also used the QR generator API, which generates the actual QR code.

### Challenges we ran into

Because this is our first hackathon, we have 2 main challenges: (1) Ideating: we had some trouble coming with up an idea, so we discussed our experiences with Canva and did research online to find several problems with Canva. (2) Programming: We had difficulty using React Native, since it was our first time using it. We had to resort to documentation and simply problem-solving whenever we ran into issues, such as when we added new buttons.

### Accomplishments we're proud of

Simply building our first-ever hackathon product - and having the perseverance to overcome any issues.

## README (from the GitHub repository)

# TreeHacks
TreeHacks Project


## Detected evidence (automated analysis)

Indexed codebase: 99 recognized source files, 271 KB.
- CSS (language) — detected in the code
- Express (technology) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (104 of 104)

```
.DS_Store
CHANGELOG.md
components/audio_player/audio_context.tsx
components/audio_player/audio_cover.css
components/audio_player/audio_cover.tsx
components/audio_player/index.ts
components/draggable_audio/draggable_audio.css
components/draggable_audio/draggable_audio.tsx
components/draggable_audio/index.ts
components/draggable_embed/draggable_embed.css
components/draggable_embed/draggable_embed.tsx
components/draggable_embed/index.ts
components/draggable_image/draggable_image.css
components/draggable_image/draggable_image.tsx
components/draggable_image/index.ts
components/draggable_text/draggable_text.css
components/draggable_text/draggable_text.tsx
components/draggable_text/index.ts
components/draggable_video/draggable_video.css
components/draggable_video/draggable_video.tsx
components/draggable_video/index.ts
declarations/declarations.d.ts
examples/app_element_children/app.tsx
examples/app_element_children/index.tsx
examples/app_embed_elements/app.tsx
examples/app_embed_elements/index.tsx
examples/app_image_elements/app.tsx
examples/app_image_elements/index.tsx
examples/app_shape_elements/app.tsx
examples/app_shape_elements/index.tsx
examples/app_text_elements/app.tsx
examples/app_text_elements/index.tsx
examples/asset_upload/app.tsx
examples/asset_upload/index.tsx
examples/authentication/app.tsx
examples/authentication/backend/.gitignore
examples/authentication/backend/database.ts
examples/authentication/backend/server.ts
examples/authentication/index.tsx
examples/authentication/README.md
examples/data_provider_basic/app.tsx
examples/data_provider_basic/index.tsx
examples/data_provider_options/app.tsx
examples/data_provider_options/index.tsx
examples/drag_and_drop_audio/app.tsx
examples/drag_and_drop_audio/index.tsx
examples/drag_and_drop_embed/app.tsx
examples/drag_and_drop_embed/index.tsx
examples/drag_and_drop_image/app.tsx
examples/drag_and_drop_image/index.tsx
examples/drag_and_drop_text/app.tsx
examples/drag_and_drop_text/index.tsx
examples/drag_and_drop_video/app.tsx
examples/drag_and_drop_video/index.tsx
examples/export/app.tsx
examples/export/index.tsx
examples/fetch/app.tsx
examples/fetch/backend/server.ts
examples/fetch/index.tsx
examples/native_embed_elements/app.tsx
examples/native_embed_elements/index.tsx
examples/native_group_elements/app.tsx
examples/native_group_elements/index.tsx
examples/native_image_elements/app.tsx
examples/native_image_elements/index.tsx
examples/native_shape_elements_with_asset/app.tsx
examples/native_shape_elements_with_asset/index.tsx
examples/native_shape_elements/app.tsx
examples/native_shape_elements/index.tsx
examples/native_text_elements/app.tsx
examples/native_text_elements/index.tsx
examples/open_external_link/app.tsx
examples/open_external_link/index.tsx
examples/page_addition/app.tsx
examples/page_addition/index.tsx
examples/page_background/app.tsx
examples/page_background/index.tsx
examples/positioning_elements/app.tsx
examples/positioning_elements/index.tsx
jest.config.js
LICENSE.md
package.json
README copy.md
README.md
scripts/ssl.js
scripts/start.js
sdk/preview/asset/index.d.ts
sdk/preview/asset/index.js
sdk/preview/data/index.d.ts
sdk/preview/data/index.js
sdk/preview/design/index.d.ts
sdk/preview/design/index.js
sdk/preview/LICENSE.md
sdk/preview/package.json
src/app.tsx
src/index.tsx
styles/components.css
tsconfig.json
utils/backend/base_backend/create.ts
utils/backend/jwt_middleware/index.ts
utils/backend/jwt_middleware/jwt_middleware.ts
utils/backend/jwt_middleware/tests/jwt_middleware.tests.ts
utils/use_selection_hook.ts
webpack.config.js
```

### Dependencies

- package.json: @canva/app-ui-kit@^3.1.0, @canva/asset@^1.2.0, @canva/design@^1.4.0, @canva/error@^1.1.0, @canva/platform@^1.0.1, @canva/preview@./sdk/preview, @canva/user@^1.0.0, @svgr/webpack@^8.0.1, @types/cookie-parser@^1.4.4, @types/cors@^2.8.13, @types/debug@^4.1.7, @types/express@^4.17.13, @types/jest@^29.4.0, @types/jsonwebtoken@^9.0.1, @types/node@^20.10.0, @types/node-fetch@^2.6.2, @types/nodemon@^1.19.2, @types/react-dom@^18.1.0, @types/webpack-env@^1.18.0, chalk@^4.1.2, cli-table3@^0.6.2, clsx@^1.2.1, cookie-parser@^1.4.6, cors@^2.8.5, css-loader@^6.7.1, css-modules-typescript-loader@^4.0.1, cssnano@^6.0.1, debug@^4.3.4, dotenv@^16.0.1, exponential-backoff@^3.1.0, express@^4.18.1, express-basic-auth@^1.2.1, jest@^29.4.2, jsonwebtoken@^9.0.0, jwks-rsa@^3.0.1, mini-css-extract-plugin@^2.6.1, ngrok@^4.3.3, node-fetch@^2.6.7, node-forge@^1.3.1, nodemon@^3.0.1, postcss-loader@^7.3.3, prettier@^2.7.1, react@^18.1.0, react-dom@^18.1.0, style-loader@^3.3.1, terser-webpack-plugin@^5.3.5, ts-jest@^29.0.5, ts-loader@^9.3.1, ts-node@^10.9.1, typescript@^5.2.2, url-loader@^4.1.1, webpack@^5.74.0, webpack-cli@^4.10.0, webpack-dev-server@^4.10.0, yargs@^17.5.1
- sdk/preview/package.json: @canva/error@^1.0.0

### Recent commits (newest first)

- some more files
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### LICENSE.md

```markdown
# A message from Canva

By making these software components available to you, our goal is to give you
the right to use the components to build your apps for Canva's ecosystem. See
below for the specific licence terms that apply to your use.

# Licence

Canva Pty Ltd (ACN 158 929 938) ("Canva") owns the copyright in the software and
associated documentation files to which this Licence relates (each a "Software
Component"). Canva reserves all of its rights.

Permission is hereby granted, free of charge, to any person obtaining a copy of
the Software Components ("You"), to use the Software Components, but strictly
subject to the following restrictions and conditions:

1. You must only use the Software Components and any Derivative on the Canva
   Platform.

2. You must only use the Software Components and any Derivative for the purpose
   of building or updating Permitted Apps, and for no other purpose.

3. You must include a copy of this Licence in all copies of any Software
   Component and Derivative.

4. To the fullest extent permitted by law, the Software Components are provided
   "as is", without warranty of any kind, express or implied, including but not
   limited to the warranties of merchantability, fitness for a particular
   purpose and non-infringement. To the fullest extent permitted by law, in no
   event shall the authors or copyright holders be liable for any claim,
   damages or other liability, whether in an action of contract, tort or
   otherwise, arising from, out of or in connection with the Software Components
   or any Derivative, or the use of or other dealings in the Software Components
   or any Derivative.

5. In this Licence:

   (a) "Canva Platform" means the visual communications platform owned and
   operated by Canva that is made available on Canva.com (as well as any
   sub-domains and international versions) and via mobile applications, desktop
   applications, and in other forms provided or made available by Canva;

   (b) "Derivative" means any software, document or other material that: (i)
   contains any Software Component; and/or (ii) comprises or contains a
   derivative, adaptation or substantial part of any Software Component; and

   (c) "Permitted App" means a software application that is solely offered to
   end-users on the Canva Platform.

```

### README copy.md

```markdown
# Canva Apps SDK starter kit

Welcome to the **Apps SDK starter kit** for Canva's app development platform. 🎉

This repo contains everything you need to get an app up and running in a matter of minutes, including a boilerplate project and lots of examples. The complete documentation for the platform is at [canva.dev/docs/apps](https://www.canva.dev/docs/apps/).

**Note:** The starter kit and documentation assumes some experience with TypeScript and React.

## Requirements

- Node.js `v18` or `v20.10.0`
- npm `v9` or `v10`

**Note:** To make sure you're running the correct version of Node.js, we recommend using a version manager, such as [nvm](https://github.com/nvm-sh/nvm#intro). The [.nvmrc](/.nvmrc) file in the root directory of this repo will ensure the correct version is used once you run `nvm install`.

## Quick start

```bash
git clone git@github.com:canva-sdks/canva-apps-sdk-starter-kit.git
cd canva-apps-sdk-starter-kit
npm install
```

## Using the boilerplate

### Step 1: Start the local development server

The `src` directory contains the boilerplate of an app.

To start the boilerplate's development server, run the following command:

```bash
npm start
```

The server becomes available at http://localhost:8080.

The app's source code is in the `src/app.tsx` file.

### Step 2: Preview the app

The local development server only exposes a JavaScript bundle, so you can't preview an app by visiting http://localhost:8080. You can only preview an app via the Canva editor.

To preview an app:

1. Create an app via the [Developer Portal](https://www.canva.com/developers).
2. Select **App source > Development URL**.
3. In the **Development URL** field, enter the URL of the development server.
4. Click **Preview**. This opens the Canva editor (and the app) in a new tab.
5. Click **Use**. (This screen only appears when when using an app for the first time.)

The app will appear in the side panel.

### (Optional) Step 3: Enable Hot Module Replacement

By default, every time you make a change to an app, you have to reload the entire app to see the results of those changes. If you enable [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) (HMR), changes will be reflected without a full reload, which significantly speeds up the development loop.

**Note:** HMR does **not** work while running the development server in a Docker container.

To enable HMR:

1. Navigate to the [Your apps](https://www.canva.com/developers/apps) page.
2. Copy the ID of an app from the **App ID** column.
3. In the starter kit's `.env` file:

   1. Set `CANVA_APP_ID` to the ID of the app.
   2. Set `CANVA_HMR_ENABLED` to `TRUE`.

   For example:

   ```bash
   CANVA_APP_ID=AABBccddeeff
   CANVA_BACKEND_PORT=3001
   CANVA_FRONTEND_PORT=8080
   CANVA_BACKEND_HOST=http://localhost:3001
   CANVA_HMR_ENABLED=TRUE
   ```

4. Restart the local server.

## Previewing apps in Safari

By default, the development server is not HTTPS-enabled. This is conveni
[truncated — 3710 more characters]
```

### package.json

```
{
  "name": "canva-apps-sdk-starter-kit",
  "description": "A boilerplate for creating Canva Apps.",
  "engines": {
    "node": "^18 || ^20.10.0",
    "npm": "^9 || ^10"
  },
  "scripts": {
    "start": "node ./scripts/start.js",
    "build": "webpack --config webpack.config.js --mode production",
    "lint:types": "tsc",
    "format": "prettier '{components,examples,src,utils}/**/*.{css,ts,tsx}' --no-config --write",
    "format:check": "prettier '{components,examples,src,utils}/**/*.{css,ts,tsx}' --no-config --check --ignore-path",
    "format:file": "prettier $1 --no-config --write",
    "test": "jest --no-cache",
    "test:watch": "jest --no-cache --watch"
  },
  "keywords": [],
  "author": "Canva Pty Ltd.",
  "license": "SEE LICENSE IN LICENSE.md",
  "private": true,
  "dependencies": {
    "@canva/app-ui-kit": "^3.1.0",
    "@canva/asset": "^1.2.0",
    "@canva/design": "^1.4.0",
    "@canva/error": "^1.1.0",
    "@canva/platform": "^1.0.1",
    "@canva/preview": "./sdk/preview",
    "@canva/user": "^1.0.0",
    "clsx": "^1.2.1",
    "cookie-parser": "^1.4.6",
    "react": "^18.1.0",
    "react-dom": "^18.1.0"
  },
  "devDependencies": {
    "@svgr/webpack": "^8.0.1",
    "@types/cookie-parser": "^1.4.4",
    "@types/cors": "^2.8.13",
    "@types/debug": "^4.1.7",
    "@types/express": "^4.17.13",
    "@types/jest": "^29.4.0",
    "@types/jsonwebtoken": "^9.0.1",
    "@types/node": "^20.10.0",
    "@types/node-fetch": "^2.6.2",
    "@types/nodemon": "^1.19.2",
    "@types/react-dom": "^18.1.0",
    "@types/webpack-env": "^1.18.0",
    "chalk": "^4.1.2",
    "cli-table3": "^0.6.2",
    "cors": "^2.8.5",
    "css-loader": "^6.7.1",
    "css-modules-typescript-loader": "^4.0.1",
    "cssnano": "^6.0.1",
    "debug": "^4.3.4",
    "dotenv": "^16.0.1",
    "exponential-backoff": "^3.1.0",
    "express": "^4.18.1",
    "express-basic-auth": "^1.2.1",
    "jest": "^29.4.2",
    "jsonwebtoken": "^9.0.0",
    "jwks-rsa": "^3.0.1",
    "mini-css-extract-plugin": "^2.6.1",
    "ngrok": "^4.3.3",
    "node-fetch": "^2.6.7",
    "node-forge": "^1.3.1",
    "nodemon": "^3.0.1",
    "postcss-loader": "^7.3.3",
    "prettier": "^2.7.1",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.5",
    "ts-jest": "^29.0.5",
    "ts-loader": "^9.3.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.2.2",
    "url-loader": "^4.1.1",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.10.0",
    "yargs": "^17.5.1"
  }
}

```

### sdk/preview/package.json

```
{
  "name": "@canva/preview",
  "version": "0.9.0",
  "description": "The Canva Apps SDK preview libraries",
  "author": "Canva Pty Ltd.",
  "license": "SEE LICENSE IN LICENSE.md",
  "private": true,
  "peerDependencies": {
    "@canva/error": "^1.0.0"
  }
}

```

### src/index.tsx

```typescript
import { AppUiProvider } from "@canva/app-ui-kit";
import * as React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./app";
import "@canva/app-ui-kit/styles.css";

const root = createRoot(document.getElementById("root")!);
function render() {
  root.render(
    <AppUiProvider>
      <App />
    </AppUiProvider>
  );
}

render();

if (module.hot) {
  module.hot.accept("./app", render);
}

```

### src/app.tsx

```typescript
import { Button, Rows, Text, TextInput } from "@canva/app-ui-kit";
import * as React from "react";
import styles from "styles/components.css";


export const App = () => {
  const [urls, setUrls] = React.useState([""]);

  const addUrlField = () => {
    setUrls([...urls, ""]);
  };

  const updateUrl = (index, newValue) => {
    const newUrls = urls.map((url, i) => (i === index ? newValue : url));
    setUrls(newUrls);
  };

  const removeUrlField = (indexToRemove) => {
    setUrls(urls.filter((_, index) => index !== indexToRemove));
  };

  const generateQRCodes = () => {
    // Placeholder for QR code generation logic
    console.log("Generating QR codes for URLs:", urls);
  };

  return (
    <div className={styles.scrollContainer}>
      <Rows spacing="2u">
        <Text>
          Enter the URLs for which you want to generate QR codes. Click "Add Another URL" to add more fields, click on the "Remove" button to remove an input, or "Generate QR Codes" when you're ready.
        </Text>
        {urls.map((url, index) => (
          <Rows key={index} spacing="2u" align="center">
            <TextInput
              value={url}
              onChange={(value) => updateUrl(index, value)}
              placeholder="Enter URL here"
              stretch
            />
            <Button variant="negative" onClick={() => removeUrlField(index)}>
              Remove
            </Button>
          </Rows>
        ))}
        <Button variant="secondary" onClick={addUrlField} stretch>
          Add Another URL
        </Button>
        <Button variant="primary" onClick={generateQRCodes} stretch>
          Generate QR Codes
        </Button>
      </Rows>
    </div>
  );
};

```

### components/draggable_text/index.ts

```typescript
export { DraggableText } from "./draggable_text";

```

### components/draggable_audio/index.ts

```typescript
export { DraggableAudio } from "./draggable_audio";

```

### components/draggable_embed/index.ts

```typescript
export { DraggableEmbed } from "./draggable_embed";

```

### components/draggable_image/index.ts

```typescript
export { DraggableImage } from "./draggable_image";

```

[89 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]