├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── configschema.json ├── eslint.browser.js ├── eslint.config.js ├── eslint.extension.js ├── package-lock.json ├── package.json ├── schemas └── exampleReplicant.json ├── src ├── browser_shared │ └── replicants.ts ├── dashboard │ ├── example │ │ ├── image.png │ │ ├── main.ts │ │ └── main.vue │ ├── quasar-variables.sass │ └── template.html ├── extension │ ├── example.ts │ ├── index.ts │ └── util │ │ ├── nodecg.ts │ │ └── replicants.ts ├── graphics │ ├── example │ │ ├── image.png │ │ ├── main.ts │ │ └── main.vue │ └── template.html └── types │ ├── ExampleType.d.ts │ ├── augment-window.d.ts │ ├── index.d.ts │ ├── schemas.d.ts │ └── schemas │ ├── configschema.d.ts │ └── exampleReplicant.d.ts ├── tsconfig.browser.json ├── tsconfig.extension.json ├── tsconfig.json ├── tsconfig.vite.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # NodeCG built files 133 | /dashboard/ 134 | /extension/ 135 | /graphics/ 136 | /shared/dist/ 137 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "syler.sass-indented", 5 | "Vue.volar", 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "explorer.fileNesting.enabled": true, 3 | "explorer.fileNesting.expand": false, 4 | "explorer.fileNesting.patterns": { 5 | "eslint.config.js": "eslint.*.js", 6 | }, 7 | "editor.tabSize": 2, 8 | "files.eol": "\n", 9 | "editor.codeActionsOnSave": { 10 | "source.organizeImports": "explicit" 11 | }, 12 | "typescript.tsdk": "node_modules\\typescript\\lib", 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 zoton2 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nodecg-vue-ts-template 2 | 3 | Template for NodeCG bundles that use Vue.js and TypeScript. 4 | 5 | 6 | ## Technical Details 7 | 8 | - Tested with Node.js v22.11.0 and above (as of writing, latest LTS properly tested and supported with NodeCG). 9 | - Extension uses TypeScript. 10 | - Browser uses Vue.js (v3), with TypeScript for the scripting. 11 | - Includes the [nodecg-vue-composable](https://github.com/Dan-Shields/nodecg-vue-composable) helper composable to help with using replicants; I advise you check it's README for more information. 12 | - Dashboard also includes Quasar, for easy styling of UI. 13 | - If you wish to configure Quasar differently, check [the quasar vite-plugin documentation](https://quasar.dev/start/vite-plugin#using-quasar). 14 | - Builds using Vite, using the [vite-plugin-nodecg](https://github.com/nodecg/vite-plugin-nodecg) plugin. 15 | - The bundle also overrides `vite` to v6 (dependency asks for v5) as it is tested working. 16 | - ESLint is included for extension/browser/typings. 17 | - Extends some other recommended configurations. 18 | - I personally use Visual Studio Code with some appropriate extensions so have made sure it works well in that editor. 19 | - Includes a `.vscode/extensions.json` that will suggest you appropriate extensions. 20 | - Includes a `.vscode/settings.json` that has some settings that you may find useful. 21 | - The extension/browser files have some example code scattered about that should help in how to use things. 22 | 23 | ## Limitations 24 | 25 | - I don't use any JSON schema specs higher than `draft-07` due to Visual Studio Code not supporting them correctly; see [this issue](https://github.com/microsoft/vscode/issues/98724). 26 | 27 | ## Package Commands 28 | 29 | - `autofix`: Automatically fix any possible linting errors using ESLint. 30 | - `prebuild`: Clean up all built/watched files; will automatically run before `build` if called. 31 | - `build`: Build written code for use in production. 32 | - `clean`: Clean up all built/watched files. 33 | - `lint`: Finds any possible linting errors using ESLint, but does not fix them. 34 | - `schema-types`: Create TypeScript typings for schemas/`Configschema.json` using `nodecg` CLI. 35 | - `start`: Start NodeCG. 36 | - `watch`: Build code and watch for changes, for use in development. 37 | 38 | ## Changelogs 39 | 40 | All changes onwards from v3.0.0 are available on the [releases](../../releases) section. Other changelogs are available below. 41 | 42 | ### Differences between template v2 and v3... 43 | 44 | This is a "brief" list of changes, although in relality it was mostly rewritten from the ground up, so there are probably more. 45 | 46 | If you want to see all of the changes, check out the [original PR](https://github.com/zoton2/nodecg-vue-ts-template/pull/24). 47 | 48 | - Switched Vite config file to TypeScript (`vite.config.mjs` > `vite.config.ts`). 49 | - Updated how the extension code is built and how it is run in a Node.js context: 50 | - It now runs using the `module` type. 51 | - It is built targetting more modern standards (based on `@tsconfig/node22`). 52 | - All updates needed for NodeCG v2, which isn't too many but is still some (mainly type related). 53 | - Bumped `package.json`s `nodecg.compatibleRange` to `^2.3.0`, as that's the first NodeCG version that properly supported Node.js v22.11.0 LTS. 54 | - Use NodeCG types from official dependency. 55 | - Replaced [@vueuse/head](https://github.com/vueuse/head) with [@unhead/vue](https://github.com/unjs/unhead), due to the former's sunsetting. 56 | - ESLint overhaul: 57 | - Upgraded from ESLint v9 from v8. 58 | - Switched to using flat configs. 59 | - A lot was stripped out that I don't think was needed (feel free to report any issues you may have). 60 | - No longer extends the configuration from airbnb-typescript, as it isn't available for ESLint v9 yet, and I wanted to try without it. 61 | - Reduced the amount of `package.json` scripts/commands by combining some of them and removing the extension/browser/etc. splits. 62 | - Added a `./src/browser_shared` folder with a shared `replicant.ts` helper file for browser contexts. 63 | - Removed MDI CSS being imported by default on dashboard panels. 64 | - Removed the `module-alias` parts as I felt they may have made things too confusing. 65 | - Moved browser `*.ts` entry files into the the respective sub-directories for better organisation. 66 | 67 | ### Differences between template v1 and v2... 68 | 69 | - Upgraded Vue to v3 from v2. 70 | - Uses Vite to build browser code instead of Webpack. 71 | - Uses Quasar for material design styling help instead of Vuetify. 72 | - No TypeScript decorators used in the browser code now as they aren't needed. 73 | - Adds [nodecg-vue-composable](https://github.com/Dan-Shields/nodecg-vue-composable) to help with using/modifying replicants in browser. 74 | - No longer includes any Vue state plugins by default (as no longer needed for replicants), but you can add one if needed (I'd suggest [pinia](https://pinia.vuejs.org/)). 75 | - Includes [@vueuse/head](https://github.com/vueuse/head), in the example code just used to help change the title of each page. 76 | - Uses the [nodecg-types](https://github.com/codeoverflow-org/nodecg-types) package instead of directly referencing the installed NodeCG instance. 77 | -------------------------------------------------------------------------------- /configschema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "additionalProperties": false, 5 | "properties": { 6 | "exampleProperty": { 7 | "type": "string" 8 | } 9 | }, 10 | "required": [ 11 | "exampleProperty" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /eslint.browser.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'; 3 | import pluginVue from 'eslint-plugin-vue'; 4 | import tseslint from 'typescript-eslint'; 5 | 6 | /* Rules used for anything browser related (dashboard and graphics). */ 7 | export default tseslint.config({ 8 | extends: defineConfigWithVueTs( 9 | pluginVue.configs['flat/recommended'], 10 | vueTsConfigs.recommended, 11 | ), 12 | rules: { 13 | // Allows "main.vue" files to be named as such. 14 | 'vue/multi-word-component-names': ['error', { ignores: ['main'] }], 15 | }, 16 | files: [ 17 | 'src/browser_shared/**/*.ts', 18 | 'src/browser_shared/**/*.vue', 19 | 'src/dashboard/**/*.ts', 20 | 'src/dashboard/**/*.vue', 21 | 'src/graphics/**/*.ts', 22 | 'src/graphics/**/*.vue', 23 | ], 24 | }); 25 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import tseslint from 'typescript-eslint'; 3 | import browser from './eslint.browser.js'; 4 | import extension from './eslint.extension.js'; 5 | 6 | /* Exists so anything looking for an ESLint config file (including VSCode and the `eslint` command) can find the rules. */ 7 | export default tseslint.config([ 8 | { 9 | ignores: [ 10 | // Ignore built files. 11 | 'dashboard/**/*', 12 | 'extension/**/*', 13 | 'graphics/**/*', 14 | 'shared/dist/**/*', 15 | ], 16 | }, 17 | browser, 18 | extension, 19 | ]); 20 | -------------------------------------------------------------------------------- /eslint.extension.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import eslint from '@eslint/js'; 3 | import tseslint from 'typescript-eslint'; 4 | 5 | /* Rules used for anything extension related (including types). */ 6 | export default tseslint.config({ 7 | extends: [ 8 | eslint.configs.recommended, 9 | tseslint.configs.recommended, 10 | ], 11 | files: [ 12 | 'src/extension/**/*.ts', 13 | 'src/types/**/*.d.ts', 14 | ], 15 | ignores: [ 16 | 'src/types/schemas/**/*.d.ts', 17 | 'src/types/env.d.ts', 18 | ], 19 | }); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodecg-vue-ts-template", 3 | "version": "3.0.0", 4 | "description": "Template for NodeCG bundles that use Vue.js and TypeScript.", 5 | "homepage": "https://github.com/zoton2/nodecg-vue-ts-template#readme", 6 | "bugs": { 7 | "url": "https://github.com/zoton2/nodecg-vue-ts-template/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/zoton2/nodecg-vue-ts-template.git" 12 | }, 13 | "license": "MIT", 14 | "author": "zoton2", 15 | "type": "module", 16 | "scripts": { 17 | "autofix": "eslint --fix", 18 | "prebuild": "trash ./extension && trash ./node_modules/.vite && trash ./shared/dist && trash ./dashboard && trash ./graphics", 19 | "build": "vite build && tsc -b tsconfig.extension.json", 20 | "lint": "eslint", 21 | "schema-types": "nodecg schema-types", 22 | "start": "cd ../.. && node index.js", 23 | "watch": "conc -n B,E -c red,blue -k vite \"tsc -b -w --preserveWatchOutput tsconfig.extension.json\"" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.25.1", 27 | "@quasar/extras": "^1.16.17", 28 | "@quasar/vite-plugin": "^1.9.0", 29 | "@tsconfig/node22": "^22.0.1", 30 | "@types/node": "^22.15.3", 31 | "@unhead/vue": "^2.0.8", 32 | "@vitejs/plugin-vue": "^5.2.3", 33 | "@vue/eslint-config-typescript": "^14.5.0", 34 | "@vue/tsconfig": "^0.7.0", 35 | "concurrently": "^9.1.2", 36 | "eslint": "^9.25.1", 37 | "eslint-plugin-vue": "^10.1.0", 38 | "nodecg": "^2.5.3", 39 | "nodecg-vue-composable": "^1.1.0", 40 | "quasar": "^2.18.1", 41 | "sass-embedded": "^1.87.0", 42 | "trash-cli": "^6.0.0", 43 | "typescript": "^5.8.3", 44 | "typescript-eslint": "^8.31.1", 45 | "vite": "^6.3.4", 46 | "vite-plugin-checker": "^0.9.1", 47 | "vite-plugin-nodecg": "^2.1.0", 48 | "vue": "^3.5.13", 49 | "vue-tsc": "^2.2.10" 50 | }, 51 | "pnpm": { 52 | "overrides": { 53 | "vite-plugin-nodecg>vite": "$vite" 54 | } 55 | }, 56 | "nodecg": { 57 | "compatibleRange": "^2.3.0", 58 | "dashboardPanels": [ 59 | { 60 | "name": "example", 61 | "title": "Example", 62 | "file": "example/main.html", 63 | "width": 3 64 | } 65 | ], 66 | "graphics": [ 67 | { 68 | "file": "example/main.html", 69 | "width": 1920, 70 | "height": 1080 71 | } 72 | ] 73 | }, 74 | "overrides": { 75 | "vite-plugin-nodecg": { 76 | "vite": "$vite" 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /schemas/exampleReplicant.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "additionalProperties": false, 5 | "properties": { 6 | "exampleProperty": { 7 | "type": "string", 8 | "default": "exampleString" 9 | } 10 | }, 11 | "required": [ 12 | "exampleProperty" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/browser_shared/replicants.ts: -------------------------------------------------------------------------------- 1 | import { useReplicant } from 'nodecg-vue-composable'; 2 | import type { Schemas } from '../types'; 3 | 4 | // YOU MUST CHANGE THIS TO YOUR BUNDLE'S NAME! 5 | const thisBundle = 'nodecg-vue-ts-template'; 6 | 7 | /** 8 | * This is where you can declare all of your replicants to import easily into other (browser based) files. 9 | * "useReplicant" is a helper composable to make accessing/modifying replicants easier. 10 | * For more information see https://github.com/Dan-Shields/nodecg-vue-composable 11 | */ 12 | export const exampleReplicant = useReplicant('exampleReplicant', thisBundle); 13 | -------------------------------------------------------------------------------- /src/dashboard/example/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoton2/nodecg-vue-ts-template/15a68b7c0cf90ead131b00ad96621173f89733ed/src/dashboard/example/image.png -------------------------------------------------------------------------------- /src/dashboard/example/main.ts: -------------------------------------------------------------------------------- 1 | import '@quasar/extras/material-icons/material-icons.css'; 2 | import '@quasar/extras/roboto-font/roboto-font.css'; 3 | import { createHead } from '@unhead/vue/client'; 4 | import { Dark, Quasar } from 'quasar'; 5 | import 'quasar/src/css/index.sass'; 6 | import { createApp } from 'vue'; 7 | import App from './main.vue'; 8 | 9 | const app = createApp(App); 10 | const head = createHead(); 11 | app.use(Quasar); 12 | app.use(head); 13 | app.mount('#app'); 14 | Dark.set(true); 15 | -------------------------------------------------------------------------------- /src/dashboard/example/main.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 33 | -------------------------------------------------------------------------------- /src/dashboard/quasar-variables.sass: -------------------------------------------------------------------------------- 1 | $primary : #00BEBE // NodeCG primary colour 2 | $secondary : #26A69A 3 | $accent : #9C27B0 4 | 5 | $dark : #1D1D1D 6 | $dark-page : #121212 7 | 8 | $positive : #21BA45 9 | $negative : #C10015 10 | $info : #31CCEC 11 | $warning : #F2C037 12 | -------------------------------------------------------------------------------- /src/dashboard/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /src/extension/example.ts: -------------------------------------------------------------------------------- 1 | import type { ExampleType } from '../types/index.js'; 2 | import { nodecg } from './util/nodecg.js'; 3 | import { exampleReplicant } from './util/replicants.js'; 4 | 5 | // Example code: 6 | // Log to show things are working. 7 | nodecg.log.info('Extension code working!'); 8 | // Access this bundle's configuration with no type assertion needed. 9 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 10 | const configProperty = nodecg.bundleConfig.exampleProperty; 11 | // Access/set a replicant (also see ./util/replicants). 12 | exampleReplicant.value = { exampleProperty: `exampleString_Changed_${Date.now()}` }; 13 | // Accessing normal types. 14 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 15 | const exampleType: ExampleType = { exampleProperty: 'exampleString' }; 16 | -------------------------------------------------------------------------------- /src/extension/index.ts: -------------------------------------------------------------------------------- 1 | import type { NodeCGServerAPI } from '../types/index.js'; 2 | import { set } from './util/nodecg.js'; 3 | 4 | export default async (nodecg: NodeCGServerAPI) => { 5 | /** 6 | * Because of how top-level `import`s work, it helps to use `import`s here 7 | * to force things to be loaded *after* the NodeCG context is set. 8 | */ 9 | set(nodecg); // set nodecg "context" before anything else 10 | await import('./util/replicants.js'); // make sure replicants are set up 11 | await import('./example.js'); 12 | }; 13 | -------------------------------------------------------------------------------- /src/extension/util/nodecg.ts: -------------------------------------------------------------------------------- 1 | import type { NodeCGServerAPI } from '../../types/index.js'; 2 | 3 | export let nodecg!: NodeCGServerAPI; 4 | 5 | export function set(ctx: NodeCGServerAPI) { 6 | nodecg = ctx; 7 | } 8 | -------------------------------------------------------------------------------- /src/extension/util/replicants.ts: -------------------------------------------------------------------------------- 1 | import type NodeCG from 'nodecg/types'; 2 | import type { Schemas } from '../../types/index.js'; 3 | import { nodecg } from './nodecg.js'; 4 | 5 | // Wrapper for replicants that have a default (based on schema). 6 | function hasDefault(name: string) { 7 | return nodecg.Replicant(name) as unknown as NodeCG.default.ServerReplicantWithSchemaDefault; 8 | } 9 | // Wrapper for replicants that don't have a default (based on schema). 10 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 11 | function hasNoDefault(name: string) { 12 | return nodecg.Replicant(name) as NodeCG.default.ServerReplicant; 13 | } 14 | 15 | /** 16 | * This is where you can declare all of your replicants to import easily into other files, 17 | * and to make sure they have any correct settings on startup. 18 | */ 19 | export const exampleReplicant = hasDefault('exampleReplicant'); 20 | -------------------------------------------------------------------------------- /src/graphics/example/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoton2/nodecg-vue-ts-template/15a68b7c0cf90ead131b00ad96621173f89733ed/src/graphics/example/image.png -------------------------------------------------------------------------------- /src/graphics/example/main.ts: -------------------------------------------------------------------------------- 1 | import { createHead } from '@unhead/vue/client'; 2 | import { createApp } from 'vue'; 3 | import App from './main.vue'; 4 | 5 | const app = createApp(App); 6 | const head = createHead(); 7 | app.use(head); 8 | app.mount('#app'); 9 | -------------------------------------------------------------------------------- /src/graphics/example/main.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 25 | -------------------------------------------------------------------------------- /src/graphics/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /src/types/ExampleType.d.ts: -------------------------------------------------------------------------------- 1 | export interface ExampleType { 2 | exampleProperty: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/types/augment-window.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a modified version of the augment-window.d.ts file included in 3 | * the NodeCG types, but allows us to automatically receive the configuration types. 4 | */ 5 | 6 | import type { NodeCGAPIClient } from '../../node_modules/nodecg/out/client/api/api.client.d.ts'; 7 | import type { Configschema } from './schemas/configschema.d.ts'; 8 | 9 | declare global { 10 | let NodeCG: typeof NodeCGAPIClient; 11 | let nodecg: NodeCGAPIClient; 12 | } 13 | -------------------------------------------------------------------------------- /src/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import type NodeCG from 'nodecg/types'; 2 | import type { Configschema } from './schemas.d.ts'; 3 | 4 | export type NodeCGServerAPI = NodeCG.default.ServerAPI; 5 | export type { ExampleType } from './ExampleType.d.ts'; 6 | export type * as Schemas from './schemas.d.ts'; 7 | -------------------------------------------------------------------------------- /src/types/schemas.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a file where the schema types can be re-exported properly. 3 | * This is for convenience; nothing is different if referenced from their files directly. 4 | * Also see index.d.ts for a "grouped" re-export of this as well. 5 | */ 6 | 7 | export type { Configschema } from './schemas/configschema.d.ts'; 8 | export type { ExampleReplicant } from './schemas/exampleReplicant.d.ts'; 9 | -------------------------------------------------------------------------------- /src/types/schemas/configschema.d.ts: -------------------------------------------------------------------------------- 1 | /* prettier-ignore */ 2 | /* eslint-disable */ 3 | /** 4 | * This file was automatically generated by json-schema-to-typescript. 5 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 6 | * and run json-schema-to-typescript to regenerate this file. 7 | */ 8 | 9 | export interface Configschema { 10 | exampleProperty: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/types/schemas/exampleReplicant.d.ts: -------------------------------------------------------------------------------- 1 | /* prettier-ignore */ 2 | /* eslint-disable */ 3 | /** 4 | * This file was automatically generated by json-schema-to-typescript. 5 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 6 | * and run json-schema-to-typescript to regenerate this file. 7 | */ 8 | 9 | export interface ExampleReplicant { 10 | exampleProperty: string; 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.browser.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Settings here partially mimick those included in a generated Vue project (npm create vue). */ 3 | /* Settings used for anything browser related (dashboard and graphics). */ 4 | "extends": "@vue/tsconfig/tsconfig.dom.json", 5 | "compilerOptions": { 6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.browser.tsbuildinfo", 7 | }, 8 | "include": [ 9 | "./src/browser_shared/**/*.ts", 10 | "./src/browser_shared/**/*.vue", 11 | "./src/dashboard/**/*.ts", 12 | "./src/dashboard/**/*.vue", 13 | "./src/graphics/**/*.ts", 14 | "./src/graphics/**/*.vue", 15 | "./src/types/**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.extension.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Settings used for anything extension related. */ 3 | "extends": "@tsconfig/node22/tsconfig.json", 4 | "compilerOptions": { 5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.extension.tsbuildinfo", 6 | "rootDir": "./src/extension", 7 | "outDir": "./extension", 8 | "verbatimModuleSyntax": true, 9 | }, 10 | "include": [ 11 | "./src/extension/**/*.ts", 12 | "./src/types/**/*.d.ts" 13 | ], 14 | "exclude": [ 15 | "./src/types/augment-window.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Exists so anything looking for a tsconfig file (including VSCode) can find the settings. */ 3 | "files": [], 4 | "references": [ 5 | { 6 | "path": "./tsconfig.browser.json" 7 | }, 8 | { 9 | "path": "./tsconfig.extension.json" 10 | }, 11 | { 12 | "path": "./tsconfig.vite.json" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /tsconfig.vite.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Settings here mimick those included in a generated Vue project (npm create vue). */ 3 | /* They are only used for the vite.config.ts file. */ 4 | "extends": "@tsconfig/node22/tsconfig.json", 5 | "compilerOptions": { 6 | "noEmit": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vite.tsbuildinfo", 8 | "module": "ESNext", 9 | "moduleResolution": "bundler", 10 | "types": [ 11 | "node" 12 | ] 13 | }, 14 | "include": [ 15 | "./vite.config.ts" 16 | ] 17 | } -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { quasar, transformAssetUrls } from '@quasar/vite-plugin'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import { fileURLToPath } from 'node:url'; 4 | import { defineConfig } from 'vite'; 5 | import checker from 'vite-plugin-checker'; 6 | import NodeCGPlugin from 'vite-plugin-nodecg'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | plugins: [ 11 | vue({ template: { transformAssetUrls } }), 12 | quasar({ 13 | autoImportComponentCase: 'pascal', 14 | sassVariables: fileURLToPath( 15 | new URL('./src/dashboard/quasar-variables.sass', import.meta.url) 16 | ) 17 | }), 18 | checker({ vueTsc: { tsconfigPath: 'tsconfig.browser.json' } }), 19 | NodeCGPlugin({ 20 | inputs: { 21 | 'graphics/*/main.ts': './src/graphics/template.html', 22 | 'dashboard/*/main.ts': './src/dashboard/template.html', 23 | }, 24 | }), 25 | ], 26 | }); 27 | --------------------------------------------------------------------------------