├── .gitignore
├── README.md
├── babel.config.js
├── env.example
├── index.html
├── package.json
├── postcss.config.js
├── src
├── App.vue
├── api
│ ├── airlock.ts
│ ├── index.js
│ └── urbitAPI.js
├── components
│ └── Start.vue
├── index.css
├── main.js
├── router
│ └── index.ts
├── shims-vue.d.ts
├── store
│ ├── index.ts
│ └── ship.ts
├── types
│ └── index.ts
└── views
│ └── Home.vue
├── tailwind.config.js
├── tsconfig.json
├── vite.config.ts
└── vue.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | package-lock.json
3 | yarn.lock
4 | .env
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vite/Vue3/Typescript/Tailwind/Urbit template
2 |
3 | Find a version of this template with:
4 |
5 | - Typed Vuex store
6 | - Vue3 `setup` components
7 | - Composition API
8 |
9 | On the
10 | [vue3-typed-store](https://github.com/vcavallo/vite-vue-urbit-template/tree/vue3-typed-store)
11 | branch.
12 |
13 |
14 | To install this elsewhere:
15 |
16 | ```
17 | npx degit vcavallo/vite-vue-urbit-template your-project-name
18 | cd your-project-name
19 |
20 | npm install
21 | ```
22 |
23 | Then:
24 |
25 | - Define a .env file, copied from env.example
26 | - Set the port based on your running fakeship
27 | - Set the desk name to the name of your desk
28 | - `npm run serve`
29 | - Visit the URL that the vite server output shows (probably `localhost:3000`)
30 | - Log in with your `+code`
31 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/env.example:
--------------------------------------------------------------------------------
1 | VITE_URBIT_TARGET='http://localhost:8080'
2 | VITE_URBIT_DESK='desk-name'
3 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite app
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-vue3-urbit-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vite --host",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@urbit/api": "^2.1.0",
12 | "@urbit/http-api": "^2.1.0",
13 | "core-js": "^3.8.3",
14 | "vue": "^3.2.25",
15 | "vue-router": "^4.0.3",
16 | "vuex": "^4.0.0"
17 | },
18 | "devDependencies": {
19 | "@typescript-eslint/eslint-plugin": "^5.4.0",
20 | "@typescript-eslint/parser": "^5.4.0",
21 | "@urbit/vite-plugin-urbit": "^0.8.0",
22 | "@vitejs/plugin-vue": "^2.3.1",
23 | "@vue/cli-plugin-babel": "~5.0.0",
24 | "@vue/cli-plugin-eslint": "~5.0.0",
25 | "@vue/cli-plugin-router": "~5.0.0",
26 | "@vue/cli-plugin-typescript": "~5.0.0",
27 | "@vue/cli-plugin-vuex": "~5.0.0",
28 | "@vue/cli-service": "~5.0.0",
29 | "@vue/eslint-config-typescript": "^9.1.0",
30 | "eslint": "^7.32.0",
31 | "eslint-config-prettier": "^8.3.0",
32 | "eslint-plugin-prettier": "^4.0.0",
33 | "eslint-plugin-vue": "^8.0.3",
34 | "prettier": "^2.4.1",
35 | "typescript": "~4.5.5",
36 | "vite": "^2.9.9",
37 | "vue-tsc": "^0.29.8",
38 | "prettier-plugin-tailwindcss": "^0.1.5",
39 | "vitawind": "^2.2.4"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 | App.vue
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
--------------------------------------------------------------------------------
/src/api/airlock.ts:
--------------------------------------------------------------------------------
1 | import urbitAPI from "./urbitAPI";
2 |
3 | interface onSubNumber {
4 | (subNumber: number): void;
5 | }
6 |
7 |
8 | export function openAirlockTo(
9 | agent: string,
10 | onEvent,
11 | onSubNumber: onSubNumber
12 | ) {
13 | urbitAPI
14 | .subscribe({
15 | app: agent,
16 | path: "/website",
17 | event: (data) => {
18 | onEvent(data);
19 | },
20 | })
21 | .then((sub: number) => {
22 | onSubNumber(sub);
23 | });
24 | }
25 |
26 | export function closeAirlock(subscription: number, onClose) {
27 | urbitAPI.unsubscribe(subscription).then(() => {
28 | onClose;
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | import urbitAPI from "./urbitAPI";
2 | import * as airlock from "./airlock";
3 |
4 | export default {
5 | ...urbitAPI,
6 | ...airlock,
7 | };
8 |
--------------------------------------------------------------------------------
/src/api/urbitAPI.js:
--------------------------------------------------------------------------------
1 | // import UrbitInterface from "@urbit/http-api"; // for typescript
2 | import connector from "@urbit/http-api";
3 |
4 | const urbitAPI = new connector("", "");
5 | urbitAPI.ship = window.ship;
6 |
7 | export default urbitAPI;
8 |
--------------------------------------------------------------------------------
/src/components/Start.vue:
--------------------------------------------------------------------------------
1 |
2 | Hello world
3 | This is Start.vue. Be sure to open this file and change const deskname
to the name of your desk.
4 |
5 |
6 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import './index.css';
5 |
6 | import { createStore } from "./store";
7 |
8 | const app = createApp(App);
9 | const store = createStore(app);
10 |
11 | app.use(store);
12 | app.use(router);
13 | app.mount("#app");
14 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory, createWebHashHistory, RouteRecordRaw } from "vue-router";
2 | import Home from "../views/Home.vue";
3 |
4 | const routes: Array = [
5 | {
6 | path: "/",
7 | name: "home",
8 | component: Home,
9 | },
10 | //{
11 | //path: "/about",
12 | //name: "about",
13 | //// route level code-splitting
14 | //// this generates a separate chunk (about.[hash].js) for this route
15 | //// which is lazy-loaded when the route is visited.
16 | //component: () =>
17 | //import([> webpackChunkName: "about" <] "../views/AboutView.vue"),
18 | //},
19 | ];
20 |
21 | const router = createRouter({
22 | history: createWebHashHistory(),
23 | routes,
24 | });
25 |
26 | export default router;
27 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | declare module '*.vue' {
3 | //import Vue from 'vue'
4 | //export default Vue
5 | import type { DefineComponent } from 'vue'
6 | const component: DefineComponent<{}, {}, any>
7 | export default component
8 | }
9 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import { createStore as createVuexStore } from "vuex";
2 |
3 | import ship from "./ship";
4 |
5 | export const createStore = () => {
6 | return createVuexStore({
7 | modules: {
8 | ship,
9 | },
10 | });
11 | };
12 |
--------------------------------------------------------------------------------
/src/store/ship.ts:
--------------------------------------------------------------------------------
1 | import airlock from "../api";
2 |
3 | import {
4 | AgentSubscription,
5 | } from "@/types";
6 |
7 | export default {
8 | namespaced: true,
9 | state() {
10 | return {
11 | subscriptions: [] as Array,
12 | };
13 | },
14 |
15 | getters: {
16 | agentSubscriptions(state): Array | [] {
17 | return state.subscriptions
18 | },
19 | },
20 |
21 | mutations: {
22 | addSubscription(state, payload: AgentSubscription) {
23 | state.subscriptions.push(payload);
24 | },
25 |
26 | unsetSubscription(state, subscription: AgentSubscription) {
27 | const sub = state.subscriptions.find((s) => s === subscription);
28 | state.subscriptions = state.subscriptions.filter((s) => s != sub);
29 | },
30 | },
31 |
32 | actions: {
33 | openAirlockToAgent({ dispatch }, agentName: string) {
34 | airlock.openAirlockTo(
35 | agentName,
36 | (data) => {
37 | console.log("agentName ", agentName);
38 | console.log("response ", data);
39 | },
40 | (subscriptionNumber: number) => {
41 | console.log("got subscription number ", subscriptionNumber);
42 | dispatch("addSubscription", {
43 | agentName,
44 | subscriptionNumber,
45 | } as AgentSubscription);
46 | }
47 | );
48 | },
49 |
50 | removeSubscription({ commit }, subscription: AgentSubscription) {
51 | commit("unsetSubscription", subscription);
52 | },
53 |
54 | addSubscription({ state, commit, dispatch }, payload: AgentSubscription) {
55 | const existing:
56 | | Array
57 | | [] = state.subscriptions.filter((s: AgentSubscription) => {
58 | return s.agentName === payload.agentName;
59 | });
60 | existing.forEach((sub) => {
61 | dispatch("removeSubscription", sub);
62 | });
63 | commit("addSubscription", payload);
64 | },
65 |
66 | closeAgentAirlocks({ commit, getters }) {
67 | const agentSubscriptions: Array | [] =
68 | getters.agentSubscriptions;
69 | agentSubscriptions.forEach((sub) => {
70 | airlock.closeAirlock(sub.subscriptionNumber, [
71 | commit("unsetSubscription", sub),
72 | ]);
73 | });
74 | },
75 | },
76 | };
77 |
--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export interface AgentSubscription {
2 | agentName: string;
3 | subscriptionNumber: number;
4 | }
5 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 | This is Home.vue
3 |
4 |
5 |
6 |
16 |
17 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ['index.html','./src/**/*.{js,jsx,ts,tsx,vue,html}'],
3 | theme: {
4 | extend: {},
5 | },
6 | plugins: [],
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "noImplicitAny": false,
8 | "noImplicitThis": true,
9 | "noImplicitReturns": true,
10 | "moduleResolution": "node",
11 | "skipLibCheck": true,
12 | "esModuleInterop": true,
13 | "allowSyntheticDefaultImports": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "useDefineForClassFields": true,
16 | "sourceMap": true,
17 | "baseUrl": ".",
18 | "types": [
19 | "webpack-env",
20 | "vite/client"
21 | ],
22 | "paths": {
23 | "@/*": [
24 | "src/types/*",
25 | "src/*"
26 | ]
27 | },
28 | "lib": [
29 | "esnext",
30 | "dom",
31 | "dom.iterable",
32 | "scripthost"
33 | ]
34 | },
35 | "include": [
36 | "src/**/*.ts",
37 | "src/**/*.tsx",
38 | "src/**/*.vue",
39 | "tests/**/*.ts",
40 | "tests/**/*.tsx"
41 | ],
42 | "exclude": [
43 | "node_modules"
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 | import { urbitPlugin } from "@urbit/vite-plugin-urbit";
4 |
5 | import path = require("path");
6 |
7 | import dotenv = require("dotenv");
8 | dotenv.config();
9 | const target = process.env.VITE_URBIT_TARGET;
10 | const base = process.env.VITE_URBIT_DESK;
11 |
12 | export default defineConfig({
13 | plugins: [vue(), urbitPlugin({ base, target })],
14 | resolve: {
15 | alias: {
16 | "@": path.resolve(__dirname, "./src"),
17 | },
18 | },
19 | build: {
20 | chunkSizeWarningLimit: 600,
21 | cssCodeSplit: false,
22 | },
23 | });
24 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("@vue/cli-service");
2 |
3 | //import dotenv = require("dotenv");
4 |
5 | //dotenv.config();
6 | //const base = process.env.URBIT_DESK;
7 |
8 | module.exports = defineConfig({
9 | transpileDependencies: true,
10 | });
11 |
--------------------------------------------------------------------------------