Skip to content

Commit

Permalink
feat(tool-nuxt): add starter
Browse files Browse the repository at this point in the history
  • Loading branch information
eunjae-lee committed Jul 26, 2024
1 parent 4c18b9f commit fe5122b
Show file tree
Hide file tree
Showing 28 changed files with 9,498 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
common
story
tool-next
tool-nuxt
space-nuxt-base
space-nuxt-base-ui
space-nuxt-starter
Expand Down
2 changes: 1 addition & 1 deletion space-plugins/nuxt-starter/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "nuxt-app",
"name": "@storyblok/space-plugin-nuxt-starter",
"private": true,
"type": "module",
"scripts": {
Expand Down
7 changes: 7 additions & 0 deletions tool-plugins/nuxt-starter/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CLIENT_ID=
CLIENT_SECRET=
BASE_URL=

# command to run a tunnel (optional)
# e.g.
# TUNNEL_COMMAND="ngrok http --hostname=your-subdomain.ngrok.io 3000"
24 changes: 24 additions & 0 deletions tool-plugins/nuxt-starter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist

# Node dependencies
node_modules

# Logs
logs
*.log

# Misc
.DS_Store
.fleet
.idea

# Local env files
.env
.env.*
!.env.example
1 change: 1 addition & 0 deletions tool-plugins/nuxt-starter/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shamefully-hoist=true
98 changes: 98 additions & 0 deletions tool-plugins/nuxt-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# `space-plugin-nuxt-starter`

This Nuxt starter is a Storyblok Space Plugin app that includes the basic authentication flow.

## Tutorial Video

If you prefer video tutorials over text, this is for you:

https://www.loom.com/share/f56defc5bfcf4fa8bce8682386f8352b?sid=8820f1b2-4229-4b05-9f22-4855e6dfccc5

## Getting Started

```sh
npx giget@latest gh:storyblok/space-tool-plugins/space-plugins/nuxt-starter YOUR-PROJECT-NAME
```

This repository is developed using [pnpm](https://pnpm.io/). However, you can also use Yarn or NPM.

```sh
cd YOUR-PROJECT-NAME

pnpm install && pnpm dev
# or
yarn install && yarn dev
# or
npm install && npm run dev
```

## Configuration

You need to create a Storyblok extension that will provide you with OAuth credentials. Then, you should add this information to your `.env` file and your hosting platform.

1. You can find the "Extensions" menu under either the Partner Portal or the My Organization.

<img src="./docs/storyblok-extensions.png" alt="Storyblok Extensions" width="200" />

2. Click the "New Extension" button in the top right corner and enter the necessary information.

<img src="./docs/new-extensions.png" alt="New Extension" width="600" />

And then you can find the information.

<img src="./docs/oauth.png" alt="OAuth information" width="600" />

3. Configure the following environment variables in `<ROOT-OF-YOUR-PROJECT>/.env`.

- `CLIENT_ID=`: Client Identifer
- `CLIENT_SECRET=`: Client Secret
- `BASE_URL=`: When using this starter, you should expose your local development server. To do this, we suggest using services like [ngrok](https://ngrok.com/). Let's say your hostname is `https://PUT-YOURS.ngrok.io`. Set that as your `BASE_URL`.

> [!NOTE]
> ngrok offers a static domain on the free plan, so you don't have to update the BASE_URL in your `.env` and Storyblok every time you get a new domain while using ngrok CLI.
<img src="./docs/ngrok-static-domain.png" alt="Static domain on ngrok" width="600" />

4. Configure your extension on Storyblok with the index URL and the redirection URL. The redirection URL ends with `/api/connect/callback`.

<img src="./docs/urls-for-oauth.png" alt="Configure URLs for oauth" width="300" />

Ensure that "Production" is the section that contains information about the production deployment, while "Preview" refers to your development environment, such as exposing localhost through ngrok.

5. App Bridge is an extra authentication layer recently introduced for Space Plugins and Tool Plugins. This starter assumes you've enabled App Bridge on the Settings page. Documentation on App Bridge will come in the near future, but you don't need to know about its inner process. This starter takes care of it out-of-the-box.

<img src="./docs/app-bridge.png" alt="App Bridge" width="600" />

If you don't see the UI to enable App Bridge, please reach out to [the Storyblok support](https://www.storyblok.com/trust-center/service-support). Or, you can disable App Bridge, by replacing your `app.config.ts` with the following.

```ts
export default defineAppConfig({
appBridge: {
type: 'space-plugin',
enabled: false,
oauth: true,
origin: 'https://app.storyblok.com',
},
auth: {
endpointPrefix: '/api/connect',
initOauthFlowUrl: `/api/connect/storyblok`,
successCallback: '/',
errorCallback: '/401',
},
});
```

6. Open the "Install Link" in a new tab and install it in your space for the development and test.

<img src="./docs/install-link.png" alt="Install Link" width="600" />

7. Start developing by running `yarn dev`, and open it on Storyblok.

<img src="./docs/open-extension.png" alt="Open the extension" width="200" />

> [!NOTE]
> If the authentication flow isn't working, please check if you have an ad blocker extension enabled in your browser and disable it.
8. Deployment

You should configure the same environment variables on the hosting platform as well.
8 changes: 8 additions & 0 deletions tool-plugins/nuxt-starter/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default defineAppConfig({
type: 'space-plugin',
appBridge: {
enabled: true,
oauth: true,
origin: 'https://app.storyblok.com',
},
});
44 changes: 44 additions & 0 deletions tool-plugins/nuxt-starter/assets/css/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

html,
body {
@apply !bg-white;
}

* {
@apply font-sans;
}

.btn-tertiary {
@apply bg-white border-ink-15 rounded-lg shadow-none font-medium;
}
.btn-tertiary:focus-visible {
@apply outline-ink-15;
}

.btn {
&-disabled,
&[disabled],
&:disabled {
@apply bg-ink-15 border-none text-ink-50 shadow-none;
}
}

.input {
background: white;
&-disabled,
&[disabled],
&:disabled {
@apply border-ink-15 bg-ink-10 text-ink-75;
}
}

.main-content {
@apply flex flex-col justify-center h-full items-center w-[26.25rem];
}

.link {
@apply text-ink-100 underline;
}
24 changes: 24 additions & 0 deletions tool-plugins/nuxt-starter/components/Header.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
const props = defineProps<{
title: string;
}>();
</script>

<template>
<div class="flex items-center gap-4">
<div class="w-10 h-10 p-2 bg-gray-100 rounded-lg">
<slot name="icon" />
</div>
<h1 class="text-2xl font-bold grow text-base-content">
{{ props.title }}
</h1>
<div>
<slot name="right-action-bar" />
</div>
</div>
<div class="mt-2 ml-14">
<div class="text-sm font-light text-gray-500">
<slot name="description" />
</div>
</div>
</template>
Binary file added tool-plugins/nuxt-starter/docs/app-bridge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tool-plugins/nuxt-starter/docs/install-link.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tool-plugins/nuxt-starter/docs/new-extensions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tool-plugins/nuxt-starter/docs/oauth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tool-plugins/nuxt-starter/docs/open-extension.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions tool-plugins/nuxt-starter/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
const config = useAppConfig();
const { completed, appBridgeAuth, oauth } = useAppBridge();
const nuxtApp = useNuxtApp();
nuxtApp.provide('appBridge', {
completed,
appBridgeAuth,
oauth,
});
</script>

<template>
<slot v-if="!config.appBridge.enabled || completed" />
</template>
30 changes: 30 additions & 0 deletions tool-plugins/nuxt-starter/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
ssr: false,
extends: [
[
'github:storyblok/space-tool-plugins/space-plugins/nuxt-base',
{ install: true },
],
[
'github:storyblok/space-tool-plugins/space-plugins/nuxt-base-ui',
{ install: true },
],
],
nitro: {
imports: {
dirs: ['./types', './utils', './server/utils'],
},
},
imports: {
dirs: ['./types', './utils'],
},
css: ['~/assets/css/base.css'],
modules: ['nuxt-lucide-icons', '@nuxtjs/google-fonts', '@nuxtjs/tailwindcss'],
googleFonts: {
families: {
Roboto: [300, 400, 500, 700],
},
},
});
32 changes: 32 additions & 0 deletions tool-plugins/nuxt-starter/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@storyblok/tool-plugin-nuxt-starter",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@storyblok/app-extension-auth": "2.0.0",
"@storyblok/region-helper": "^1.1.0",
"storyblok-js-client": "^6.2.0"
},
"devDependencies": {
"@nuxt/eslint-config": "^0.2.0",
"@nuxtjs/google-fonts": "3.1.0",
"@nuxtjs/tailwindcss": "^6.11.0",
"autoprefixer": "10.4.16",
"daisyui": "^4.4.19",
"eslint": "^8.56.0",
"eslint-plugin-vuejs-accessibility": "^2.2.1",
"nuxt": "3.11.1",
"nuxt-lucide-icons": "1.0.3",
"vue": "^3.4.14",
"vue-router": "^4.2.5"
}
}
43 changes: 43 additions & 0 deletions tool-plugins/nuxt-starter/pages/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script setup lang="ts">
const { data } = await useFetch('/api/stories');
const alert = useAlert();
</script>

<template>
<div>
<div class="mx-20 my-11">
<Header title="Nuxt Starter">
<template #icon>
<LucideTornado class="text-primary" />
</template>
<template #description>
This is a `space-plugin-nuxt-starter`.
</template>
<!-- <template #right-action-bar>
<button class="btn btn-outline">
<span class="text-base">Settings</span><LucideSettings :size="16" />
</button>
</template> -->
</Header>

<div v-if="data">
<p class="mt-10 text-sm font-thin text-gray-600">
Total number of stories: {{ data.total }}
</p>
<ul class="mt-4 space-y-4">
<li v-for="story in data.stories" :key="story.id">
<span class="text-lg">{{ story.name }}</span>
<span class="ml-2 text-sm font-thin text-gray-600"
>(/{{ story.slug }})</span
>
</li>
</ul>
</div>
</div>
</div>
<BaseAlert
v-if="alert.state.show"
:message="alert.state.message"
:type="alert.state.type"
/>
</template>
Loading

0 comments on commit fe5122b

Please sign in to comment.