Repository: strapi/strapi-starter-nuxt-e-commerce
Branch: master
Commit: 27aebc53d41d
Files: 23
Total size: 21.8 KB
Directory structure:
gitextract_fb3yuxxp/
├── .gitignore
├── LICENSE.txt
├── README.md
├── starter/
│ ├── .gitignore
│ ├── assets/
│ │ ├── README.md
│ │ └── css/
│ │ └── tailwind.css
│ ├── components/
│ │ ├── Buttons.vue
│ │ ├── Footer.vue
│ │ ├── Navbar.vue
│ │ ├── Products.vue
│ │ └── icons/
│ │ ├── cart.vue
│ │ ├── facebook.vue
│ │ ├── github.vue
│ │ └── twitter.vue
│ ├── layouts/
│ │ └── default.vue
│ ├── nuxt.config.js
│ ├── package.json
│ ├── pages/
│ │ ├── categories/
│ │ │ └── _id.vue
│ │ ├── index.vue
│ │ └── products/
│ │ └── _id.vue
│ ├── tailwind.config.js
│ └── utils/
│ └── medias.js
└── starter.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/macos,visualstudiocode,windows
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,visualstudiocode,windows
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### VisualStudioCode ###
.vscode/*
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/macos,visualstudiocode,windows
================================================
FILE: LICENSE.txt
================================================
MIT License
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS 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 NONINFRINGEMENT. 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 OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
**:no_entry: Deprecated**
This repository is no longer maintained and only works for Strapi v3. To find the newest Strapi v4 starters, check out the [starters-and-templates monorepo](https://github.com/strapi/starters-and-templates/).
---
# Strapi Starter Nuxt.js E-commerce
Nuxt.js starter for creating a simple e-commerce website with Strapi.

This starter allows you to try Strapi with Nuxt.js with the example of a simple e-commerce website where you can buy dev stickers. It is fully customizable and due to the fact that it is open source, fully open to contributions. So do not hesitate to add new features and report bugs!
This starter uses the [Strapi corporate template](https://github.com/strapi/strapi-template-ecommerce)
Check out all of our starters [here](https://strapi.io/starters)
## Features
- 1 Component
- 2 Collection types: Product, Category
- 27 Created products
- 6 Created categories
- Permissions set to `true` for product and category
- Responsive design using Tailwind css
- Slug system
- Publication system (draft & published)
- Role based access controls
- [@nuxt/strapi](https://strapi.nuxtjs.org/) module on the frontend
- Payments handled with Snipcart
This starter is using [Snipcart](https://snipcart.com/) which allows you setup a shopping cart on any website. They wrote a [tutorial](https://snipcart.com/blog/strapi-nuxt-ecommerce-tutorial) teaching you how to create this website but selling cupcakes!
Payment will not work on localhost, we are redirecting you to this [tutorial](https://snipcart.com/blog/develop-a-snipcart-powered-website-locally-using-ngrok) if you want to test payment locally.
## Getting started
Use our `create-strapi-starter` CLI to create your project.
```sh
npx create-strapi-starter@3 my-site nuxt-e-commerce
```
The CLI will create a monorepo, install dependencies, and run your project automatically.
The Nuxt frontend server will run here => [http://localhost:3000](http://localhost:3000)
The Strapi backend server will run here => [http://localhost:1337](http://localhost:1337)
## Deploying to production
You will need to deploy the `frontend` and `backend` projects separately. Here are the docs to deploy each one:
- [Deploy Strapi](https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/deployment.html#hosting-provider-guides)
- [Deploy Nuxt](https://nuxtjs.org/docs/2.x/deployment/deploying-to-21yunbox)
Don't forget to setup the environment variables on your production app:
For the frontend the following environment variable is required:
- `API_URL`: URL of your Strapi backend, without trailing slash
Enjoy this starter!
================================================
FILE: starter/.gitignore
================================================
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# test snapshots
test/**/__snapshots__
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE
.idea
# Service worker
sw.*
.DS_Store
================================================
FILE: starter/assets/README.md
================================================
# ASSETS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
================================================
FILE: starter/assets/css/tailwind.css
================================================
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
================================================
FILE: starter/components/Buttons.vue
================================================
<template>
<div class="">
<div v-if="error">
{{ error }}
</div>
<div v-else>
<div class="container flex flex-wrap mx-auto ml-4 mr-6 mt-8">
<nuxt-link v-for="category in categories" :to="`/categories/${category.slug}`" :key="category.id" class="bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 ml-2 border border-gray-400 rounded shadow">
{{ category.name }}
</nuxt-link>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
categories: [],
error: null
}
},
async mounted() {
try {
this.categories = await this.$strapi.find('categories')
} catch (error) {
this.error = error
}
},
}
</script>
<style lang="css" scoped>
</style>
================================================
FILE: starter/components/Footer.vue
================================================
<template>
<div class="flex justify-between m-6">
<p class="text-xs font-semibold text-gray-600">Strapi Starter Nuxt.js E-commerce</p>
<div class="flex">
<a href="https://twitter.com/strapijs" class="max-w-xs ml-4">
<Twitter />
</a>
<a href="https://facebook.com/strapijs" class="ml-3">
<Facebook />
</a>
<a href="https://github.com/strapi/strapi-starter-nuxt-e-commerce" class="ml-3">
<Github />
</a>
</div>
</div>
</template>
<script>
import Twitter from "~/components/icons/twitter.vue";
import Github from "~/components/icons/github.vue";
import Facebook from "~/components/icons/facebook.vue";
export default {
components: {
Twitter,
Github,
Facebook
}
}
</script>
<style>
.emoji {
font-size: 30px;
}
</style>
================================================
FILE: starter/components/Navbar.vue
================================================
<template>
<div class="flex justify-between ml-6 mr-6 mt-4">
<nuxt-link to="/">
<span class="emoji">
<img src="~/assets/strapi.png" class="logo" height="150" width="150" />
</span>
</nuxt-link>
<button class="snipcart-checkout flex items-center">
<Cart />
<span class="snipcart-total-price ml-3 font-semibold text-sm text-indigo-500"></span>
</button>
</div>
</template>
<script>
import Cart from "./icons/cart.vue"
export default {
components: {
Cart
}
}
</script>
<style>
.emoji {
font-size: 30px;
}
</style>
================================================
FILE: starter/components/Products.vue
================================================
<template>
<div>
<div v-if="error">
{{ error }}
</div>
<div class="m-6 grid grid-cols-1 sm:grid-cols-3 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 gap-4 mt-8" v-else>
<div v-for="product in products" :key="product.id" class="border rounded-lg bg-gray-100 hover:shadow-lg shadow-md">
<nuxt-link :to="`/products/${product.slug}`">
<div class="rounded-t-lg bg-white pt-2 pb-2">
<img v-lazy class="crop mx-auto" src="~/assets/img/placeholder-image.png" :data-src="`${getStrapiMedia(product.image.formats.thumbnail.url)}`">
</div>
<div class="pl-4 pr-4 pb-4 pt-4 rounded-lg">
<h4 class="mt-1 font-semibold text-base leading-tight truncate text-gray-700">{{product.title}} sticker</h4>
<div class="mt-1 text-sm text-gray-700">{{product.description}}</div>
</div>
</nuxt-link>
</div>
</div>
</div>
</template>
<script>
import {
getStrapiMedia
} from '~/utils/medias'
export default {
props: {
products: Array,
error: Object,
storeUrl: String
},
directives: {
lazy: {
inserted: (el) => {
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
observer.unobserve(el);
}
});
});
observer.observe(el);
},
},
},
methods: {
getStrapiMedia
}
}
</script>
<style>
.crop {
width: 180px;
height: 180px;
}
</style>
================================================
FILE: starter/components/icons/cart.vue
================================================
<template>
<svg width="31" height="100%" viewBox="0 0 31 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M1.10512 0.368718C0.560256 0.368718 0.118164 0.812066 0.118164 1.35848C0.118164 1.9049 0.560256 2.34824 1.10512 2.34824H4.90887L8.30138 18.4009C8.43503 19.0053 8.83085 19.5079 9.32946 19.5041H25.7788C26.3005 19.5118 26.7799 19.0375 26.7799 18.5143C26.7799 17.9911 26.3006 17.5168 25.7788 17.5245H10.1315L9.71003 15.545H27.095C27.5371 15.5412 27.9547 15.2048 28.0511 14.7718L30.354 4.87412C30.4825 4.29933 29.9852 3.67172 29.3979 3.66786H7.21171L6.6771 1.15221C6.58329 0.71276 6.15921 0.368652 5.7107 0.368652L1.10512 0.368718ZM7.623 5.64746H12.7634L13.2569 8.61674H8.25005L7.623 5.64746ZM14.7785 5.64746H20.9881L20.4946 8.61674H15.2719L14.7785 5.64746ZM23.0031 5.64746H28.1537L27.4649 8.61674H22.5097L23.0031 5.64746ZM8.67181 10.5963H13.5862L14.0797 13.5656H9.29919L8.67181 10.5963ZM15.6009 10.5963H20.1656L19.6721 13.5656H16.0944L15.6009 10.5963ZM22.1807 10.5963H27.0023L26.3135 13.5656H21.6872L22.1807 10.5963ZM12.6197 20.164C10.8141 20.164 9.32979 21.6525 9.32979 23.4632C9.32979 25.2739 10.8141 26.7624 12.6197 26.7624C14.4252 26.7624 15.9095 25.2739 15.9095 23.4632C15.9095 21.6525 14.4252 20.164 12.6197 20.164ZM22.4892 20.164C20.6837 20.164 19.1994 21.6525 19.1994 23.4632C19.1994 25.2739 20.6837 26.7624 22.4892 26.7624C24.2948 26.7624 25.7791 25.2739 25.7791 23.4632C25.7791 21.6525 24.2948 20.164 22.4892 20.164ZM12.6197 22.1435C13.3586 22.1435 13.9356 22.7222 13.9356 23.4632C13.9356 24.2042 13.3586 24.7829 12.6197 24.7829C11.8807 24.7829 11.3037 24.2042 11.3037 23.4632C11.3037 22.7222 11.8807 22.1435 12.6197 22.1435ZM22.4892 22.1435C23.2282 22.1435 23.8052 22.7222 23.8052 23.4632C23.8052 24.2042 23.2282 24.7829 22.4892 24.7829C21.7503 24.7829 21.1733 24.2042 21.1733 23.4632C21.1733 22.7222 21.7503 22.1435 22.4892 22.1435Z"
class="fill-current text-indigo-500"
/>
</svg>
</template>
================================================
FILE: starter/components/icons/facebook.vue
================================================
<template>
<svg
id="Bold"
enable-background="new 0 0 24 24"
viewBox="0 0 24 24"
height="20px"
width="20px"
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-gray-600"
>
<path
d="m15.997 3.985h2.191v-3.816c-.378-.052-1.678-.169-3.192-.169-3.159 0-5.323 1.987-5.323 5.639v3.361h-3.486v4.266h3.486v10.734h4.274v-10.733h3.345l.531-4.266h-3.877v-2.939c.001-1.233.333-2.077 2.051-2.077z"
/>
</svg>
</template>
================================================
FILE: starter/components/icons/github.vue
================================================
<template>
<svg
enable-background="new 0 0 24 24"
height="20px"
width="20px"
viewBox="0 0 24 24"
class="fill-current text-gray-600"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m12 .5c-6.63 0-12 5.28-12 11.792 0 5.211 3.438 9.63 8.205 11.188.6.111.82-.254.82-.567 0-.28-.01-1.022-.015-2.005-3.338.711-4.042-1.582-4.042-1.582-.546-1.361-1.335-1.725-1.335-1.725-1.087-.731.084-.716.084-.716 1.205.082 1.838 1.215 1.838 1.215 1.07 1.803 2.809 1.282 3.495.981.108-.763.417-1.282.76-1.577-2.665-.295-5.466-1.309-5.466-5.827 0-1.287.465-2.339 1.235-3.164-.135-.298-.54-1.497.105-3.121 0 0 1.005-.316 3.3 1.209.96-.262 1.98-.392 3-.398 1.02.006 2.04.136 3 .398 2.28-1.525 3.285-1.209 3.285-1.209.645 1.624.24 2.823.12 3.121.765.825 1.23 1.877 1.23 3.164 0 4.53-2.805 5.527-5.475 5.817.42.354.81 1.077.81 2.182 0 1.578-.015 2.846-.015 3.229 0 .309.21.678.825.56 4.801-1.548 8.236-5.97 8.236-11.173 0-6.512-5.373-11.792-12-11.792z"
/>
</svg>
</template>
================================================
FILE: starter/components/icons/twitter.vue
================================================
<template>
<svg
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
height="20px"
width="20px"
viewBox="0 0 512 512"
style="enable-background:new 0 0 512 512;"
xml:space="preserve"
class="fill-current text-gray-600"
>
<g>
<g>
<path
d="M512,97.248c-19.04,8.352-39.328,13.888-60.48,16.576c21.76-12.992,38.368-33.408,46.176-58.016
c-20.288,12.096-42.688,20.64-66.56,25.408C411.872,60.704,384.416,48,354.464,48c-58.112,0-104.896,47.168-104.896,104.992
c0,8.32,0.704,16.32,2.432,23.936c-87.264-4.256-164.48-46.08-216.352-109.792c-9.056,15.712-14.368,33.696-14.368,53.056
c0,36.352,18.72,68.576,46.624,87.232c-16.864-0.32-33.408-5.216-47.424-12.928c0,0.32,0,0.736,0,1.152
c0,51.008,36.384,93.376,84.096,103.136c-8.544,2.336-17.856,3.456-27.52,3.456c-6.72,0-13.504-0.384-19.872-1.792
c13.6,41.568,52.192,72.128,98.08,73.12c-35.712,27.936-81.056,44.768-130.144,44.768c-8.608,0-16.864-0.384-25.12-1.44
C46.496,446.88,101.6,464,161.024,464c193.152,0,298.752-160,298.752-298.688c0-4.64-0.16-9.12-0.384-13.568
C480.224,136.96,497.728,118.496,512,97.248z"
/>
</g>
</g>
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
<g />
</svg>
</template>
================================================
FILE: starter/layouts/default.vue
================================================
<template>
<div class="flex justify-center bg-gray-200">
<div class="max-w-screen-lg flex flex-col min-h-screen w-full">
<NavBar />
<Buttons />
<Nuxt class="flex-grow" />
<Footer />
</div>
<div hidden id="snipcart" data-api-key="ODhhNWUxOGEtNTk0OC00OTQwLWJkOWMtM2M1ZmNjODU1ZDJhNjM3MzMyNzM0NjM1OTMyNjcz"></div>
</div>
</template>
<script>
import NavBar from './../components/Navbar'
import Footer from './../components/Footer'
import Buttons from './../components/Buttons'
export default {
components: {
NavBar,
Footer,
Buttons
}
}
</script>
================================================
FILE: starter/nuxt.config.js
================================================
export default {
/*
** Nuxt target
** See https://nuxtjs.org/api/configuration-target
*/
target: 'static',
/*
** Headers of the page
** See https://nuxtjs.org/api/configuration-head
*/
// <script src="https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.js"></script>
head: {
title: "Buy stickers with Strapi, Nuxt.js and Snipcart",
meta: [{
charset: 'utf-8'
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1'
},
{
hid: 'description',
name: 'description',
content: "e-commerce starter using Strapi, Nuxt.js and Snipcart"
}
],
link: [{
rel: 'preconnect',
href: "https://app.snipcart.com"
},
{
rel: 'preconnect',
href: "https://cdn.snipcart.com"
},
{
rel: 'stylesheet',
href: "https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.css"
},
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico'
}
],
script: [{
src: 'https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.js'
}]
},
/*
** Global CSS
*/
css: [],
/*
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [],
/*
** Auto import components
** See https://nuxtjs.org/api/configuration-components
*/
components: true,
/*
** Nuxt.js dev-modules
*/
buildModules: [
// Doc: https://github.com/nuxt-community/nuxt-tailwindcss
'@nuxtjs/tailwindcss',
],
/*
** Nuxt.js modules
*/
modules: ['@nuxtjs/strapi'],
strapi: {
url: process.env.API_URL || "http://localhost:1337",
entities: [
'products',
'categories'
],
},
env: {
storeUrl: process.env.STORE_URL || "http://localhost:1337"
},
/*
** Build configuration
** See https://nuxtjs.org/api/configuration-build/
*/
build: {}
}
================================================
FILE: starter/package.json
================================================
{
"name": "nuxt-strapi-snipcart",
"version": "1.0.0",
"private": true,
"scripts": {
"develop": "nuxt",
"start": "nuxt start",
"serve": "nuxt serve",
"generate": "nuxt generate"
},
"dependencies": {
"@nuxtjs/strapi": "^0.1.3",
"core-js": "^2.6.5",
"nuxt": "^2.14.6",
"vue-meta": "^2.4.0"
},
"devDependencies": {
"@nuxtjs/tailwindcss": "^2.0.0"
}
}
================================================
FILE: starter/pages/categories/_id.vue
================================================
<template>
<Products :products="this.category.products" :error="error" />
</template>
<script>
import Products from "~/components/Products.vue"
export default {
data() {
return {
category: {},
error: null
}
},
async mounted() {
try {
this.category = await this.$strapi.$categories.findOne(this.$route.params.id)
} catch (error) {
this.error = error
}
},
components: {
Products
}
}
</script>
================================================
FILE: starter/pages/index.vue
================================================
<template>
<Products :products="products" :error="error" :storeUrl="storeUrl" />
</template>
<script>
import Products from "~/components/Products.vue"
export default {
data() {
return {
products: [],
storeUrl: process.env.storeUrl,
error: null
}
},
async mounted() {
try {
this.products = await this.$strapi.$products.find()
} catch (error) {
this.error = error
}
},
components: {
Products
}
}
</script>
================================================
FILE: starter/pages/products/_id.vue
================================================
<template>
<div v-if="this.product !== null">
<div class="m-6 mt-56 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-4 mt-8">
<div class="rounded-t-lg pt-2 pb-2">
<img :src="`${getStrapiMedia(product.image.formats.thumbnail.url)}`" class="m-auto">
</div>
<div class="w-full p-5 flex flex-col justify-between">
<div>
<h4 class="mt-1 font-semibold text-lg leading-tight truncate text-gray-700">{{product.title}} - ${{ product.price }}</h4>
<div class="mt-1 text-gray-600">{{ product.description }}</div>
</div>
<button v-if="product.status === 'published'" class="snipcart-add-item mt-4 bg-white border border-gray-200 d hover:shadow-lg text-gray-700 font-semibold py-2 px-4 rounded shadow" :data-item-id="product.id" :data-item-price="product.price"
:data-item-url="`${this.$route.fullPath}`" :data-item-description="product.description" :data-item-image="`${getStrapiMedia(product.image.formats.thumbnail.url)}`" :data-item-name="product.title" v-bind="customFields">
Add to cart
</button>
<div class="text-center mr-10 mb-1" v-else>
<div class="p-2 bg-indigo-800 items-center text-indigo-100 leading-none lg:rounded-full flex lg:inline-flex" role="alert">
<span class="flex rounded-full bg-indigo-500 uppercase px-2 py-1 text-xs font-bold mr-3">Coming soon...</span>
<span class="font-semibold mr-2 text-left flex-auto">This article is not available yet.</span>
</div>
</div>
</div>
</div>
</div>
<div v-else>
{{ error }}
</div>
</template>
<script>
import {
getStrapiMedia
} from '~/utils/medias'
export default {
data() {
return {
product: null,
error: null
}
},
async mounted() {
try {
this.product = await this.$strapi.$products.findOne(this.$route.params.id)
} catch (error) {
this.error = error
}
},
computed: {
customFields() {
return this.product["Custom_field"]
.map(({
title,
required,
options
}) => ({
name: title,
required,
options
}))
.map((x, index) => Object.entries(x)
.map(([key, value]) => ({
[`data-item-custom${index + 1}-${key.toString().toLowerCase()}`]: value
})))
.reduce((acc, curr) => acc.concat(curr), [])
.reduce((acc, curr) => ({
...acc,
...curr
}))
}
},
methods: {
getStrapiMedia
}
}
</script>
================================================
FILE: starter/tailwind.config.js
================================================
/*
** TailwindCSS Configuration File
**
** Docs: https://tailwindcss.com/docs/configuration
** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js
*/
module.exports = {
theme: {},
variants: {},
plugins: [],
purge: {
// Learn more on https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css
enabled: process.env.NODE_ENV === 'production',
content: [
'components/**/*.vue',
'layouts/**/*.vue',
'pages/**/*.vue',
'plugins/**/*.js',
'nuxt.config.js'
]
}
}
================================================
FILE: starter/utils/medias.js
================================================
export function getStrapiMedia(url) {
// Check if URL is a local path
if (url.startsWith('/')) {
// Prepend Strapi address
return `http://localhost:1337${url}`
}
// Otherwise return full URL
return url
}
================================================
FILE: starter.json
================================================
{
"template": "https://github.com/strapi/strapi-template-ecommerce"
}
gitextract_fb3yuxxp/ ├── .gitignore ├── LICENSE.txt ├── README.md ├── starter/ │ ├── .gitignore │ ├── assets/ │ │ ├── README.md │ │ └── css/ │ │ └── tailwind.css │ ├── components/ │ │ ├── Buttons.vue │ │ ├── Footer.vue │ │ ├── Navbar.vue │ │ ├── Products.vue │ │ └── icons/ │ │ ├── cart.vue │ │ ├── facebook.vue │ │ ├── github.vue │ │ └── twitter.vue │ ├── layouts/ │ │ └── default.vue │ ├── nuxt.config.js │ ├── package.json │ ├── pages/ │ │ ├── categories/ │ │ │ └── _id.vue │ │ ├── index.vue │ │ └── products/ │ │ └── _id.vue │ ├── tailwind.config.js │ └── utils/ │ └── medias.js └── starter.json
SYMBOL INDEX (1 symbols across 1 files)
FILE: starter/utils/medias.js
function getStrapiMedia (line 1) | function getStrapiMedia(url) {
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (25K chars).
[
{
"path": ".gitignore",
"chars": 1195,
"preview": "\n# Created by https://www.toptal.com/developers/gitignore/api/macos,visualstudiocode,windows\n# Edit at https://www.topta"
},
{
"path": "LICENSE.txt",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) [year] [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "README.md",
"chars": 2687,
"preview": "**:no_entry: Deprecated**\n\nThis repository is no longer maintained and only works for Strapi v3. To find the newest Stra"
},
{
"path": "starter/.gitignore",
"chars": 1204,
"preview": "### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.p"
},
{
"path": "starter/assets/README.md",
"chars": 296,
"preview": "# ASSETS\n\n**This directory is not required, you can delete it if you don't want to use it.**\n\nThis directory contains yo"
},
{
"path": "starter/assets/css/tailwind.css",
"chars": 95,
"preview": "@import 'tailwindcss/base';\n@import 'tailwindcss/components';\n@import 'tailwindcss/utilities';\n"
},
{
"path": "starter/components/Buttons.vue",
"chars": 761,
"preview": "<template>\n<div class=\"\">\n <div v-if=\"error\">\n {{ error }}\n </div>\n <div v-else>\n <div class=\"container flex fl"
},
{
"path": "starter/components/Footer.vue",
"chars": 783,
"preview": "<template>\n<div class=\"flex justify-between m-6\">\n <p class=\"text-xs font-semibold text-gray-600\">Strapi Starter Nuxt.j"
},
{
"path": "starter/components/Navbar.vue",
"chars": 556,
"preview": "<template>\n<div class=\"flex justify-between ml-6 mr-6 mt-4\">\n <nuxt-link to=\"/\">\n <span class=\"emoji\">\n <img sr"
},
{
"path": "starter/components/Products.vue",
"chars": 1601,
"preview": "<template>\n<div>\n <div v-if=\"error\">\n {{ error }}\n </div>\n <div class=\"m-6 grid grid-cols-1 sm:grid-cols-3 md:grid"
},
{
"path": "starter/components/icons/cart.vue",
"chars": 1942,
"preview": "<template>\n <svg width=\"31\" height=\"100%\" viewBox=\"0 0 31 27\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path"
},
{
"path": "starter/components/icons/facebook.vue",
"chars": 461,
"preview": "<template>\n <svg\n id=\"Bold\"\n enable-background=\"new 0 0 24 24\"\n viewBox=\"0 0 24 24\"\n height=\"20px\"\n widt"
},
{
"path": "starter/components/icons/github.vue",
"chars": 989,
"preview": "<template>\n <svg\n enable-background=\"new 0 0 24 24\"\n height=\"20px\"\n width=\"20px\"\n viewBox=\"0 0 24 24\"\n c"
},
{
"path": "starter/components/icons/twitter.vue",
"chars": 1413,
"preview": "<template>\n <svg\n version=\"1.1\"\n id=\"Capa_1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w"
},
{
"path": "starter/layouts/default.vue",
"chars": 581,
"preview": "<template>\n<div class=\"flex justify-center bg-gray-200\">\n <div class=\"max-w-screen-lg flex flex-col min-h-screen w-full"
},
{
"path": "starter/nuxt.config.js",
"chars": 1967,
"preview": "export default {\n /*\n ** Nuxt target\n ** See https://nuxtjs.org/api/configuration-target\n */\n target: 'static',\n"
},
{
"path": "starter/package.json",
"chars": 401,
"preview": "{\n \"name\": \"nuxt-strapi-snipcart\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"scripts\": {\n \"develop\": \"nuxt\",\n \""
},
{
"path": "starter/pages/categories/_id.vue",
"chars": 455,
"preview": "<template>\n <Products :products=\"this.category.products\" :error=\"error\" />\n</template>\n\n<script>\nimport Products from \""
},
{
"path": "starter/pages/index.vue",
"chars": 472,
"preview": "<template>\n<Products :products=\"products\" :error=\"error\" :storeUrl=\"storeUrl\" />\n</template>\n\n<script>\nimport Products f"
},
{
"path": "starter/pages/products/_id.vue",
"chars": 2543,
"preview": "<template>\n<div v-if=\"this.product !== null\">\n <div class=\"m-6 mt-56 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:"
},
{
"path": "starter/tailwind.config.js",
"chars": 563,
"preview": "/*\n** TailwindCSS Configuration File\n**\n** Docs: https://tailwindcss.com/docs/configuration\n** Default: https://github.c"
},
{
"path": "starter/utils/medias.js",
"chars": 222,
"preview": "export function getStrapiMedia(url) {\n // Check if URL is a local path\n if (url.startsWith('/')) {\n // Prepend Stra"
},
{
"path": "starter.json",
"chars": 72,
"preview": "{\n \"template\": \"https://github.com/strapi/strapi-template-ecommerce\"\n}\n"
}
]
About this extraction
This page contains the full source code of the strapi/strapi-starter-nuxt-e-commerce GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (21.8 KB), approximately 7.9k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.