├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── scripts │ ├── bump-edge.ts │ ├── cleanup.sh │ ├── release-edge.sh │ └── release.sh └── workflows │ ├── ci-dev.yml │ ├── ci.yml │ └── studio.yml ├── .gitignore ├── .npmrc ├── .starters └── default │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── app.config.ts │ ├── content │ ├── 1.index.md │ ├── 2.articles.md │ ├── 3.contact.md │ └── articles │ │ ├── 1.get-started.md │ │ ├── 2.configure.md │ │ ├── 3.write-articles.md │ │ └── 4.design-tokens.md │ ├── nuxt.config.ts │ ├── package.json │ ├── public │ ├── alpine-0.webp │ ├── alpine-1.webp │ ├── alpine-2.webp │ ├── articles │ │ ├── configure-alpine.webp │ │ ├── design-tokens.webp │ │ ├── get-started.webp │ │ └── write-articles.webp │ ├── design-tokens-studio.png │ ├── logo-dark.svg │ ├── logo.svg │ └── social-card-preview.png │ ├── renovate.json │ ├── tokens.config.ts │ └── tsconfig.json ├── LICENSE ├── README.md ├── app.config.ts ├── app.vue ├── assets └── main.css ├── components ├── AppFooter.vue ├── AppHeader.vue ├── AppLayout.vue ├── AppLoadingBar.vue ├── Button.vue ├── ColorModeSwitch.vue ├── DocumentDrivenNotFound.vue ├── MainNav.vue ├── SocialIcons.vue ├── content │ ├── ArticlesList.vue │ ├── ArticlesListItem.vue │ ├── ContactForm.vue │ ├── Gallery.vue │ └── Hero.vue └── data-entry │ └── Input.vue ├── composables └── date.ts ├── layouts ├── article.vue ├── default.vue └── page.vue ├── nuxt.config.ts ├── nuxt.schema.ts ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── renovate.json ├── tokens.config.ts ├── tsconfig.json └── types └── contact.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .output 4 | .nuxt 5 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@nuxt/eslint-config'], 4 | rules: { 5 | // Global 6 | semi: ['error', 'never'], 7 | quotes: ['error', 'single'], 8 | 'quote-props': ['error', 'as-needed'], 9 | 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }], 10 | 11 | // Vue 12 | indent: ['error', 2], 13 | 'vue/multi-word-component-names': 0, 14 | 'vue/no-v-html': 0 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/scripts/bump-edge.ts: -------------------------------------------------------------------------------- 1 | import { promises as fsp } from 'fs' 2 | import { resolve } from 'path' 3 | import { execSync } from 'child_process' 4 | 5 | const loadPackage = async (dir: string) => { 6 | const pkgPath = resolve(dir, 'package.json') 7 | 8 | const data = JSON.parse(await fsp.readFile(pkgPath, 'utf-8').catch(() => '{}')) 9 | 10 | const save = () => fsp.writeFile(pkgPath, `${JSON.stringify(data, null, 2)}\n`) 11 | 12 | return { 13 | dir, 14 | data, 15 | save, 16 | } 17 | } 18 | 19 | const main = async () => { 20 | const path = process.argv[2] 21 | 22 | const pkg = await loadPackage(path) 23 | 24 | const commit = execSync('git rev-parse --short HEAD').toString('utf-8').trim() 25 | 26 | const version = `${pkg.data.version}-${commit}` 27 | 28 | if (!pkg.data.name.includes('-edge')) pkg.data.name = `${pkg.data.name}-edge` 29 | 30 | if (!pkg.data.version.includes(commit)) pkg.data.version = version 31 | 32 | pkg.save() 33 | } 34 | 35 | main().catch((err) => { 36 | console.error(err) 37 | process.exit(1) 38 | }) 39 | -------------------------------------------------------------------------------- /.github/scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Root 4 | rm -rf node_modules 5 | rm -rf yarn.lock 6 | 7 | # Docs 8 | rm -rf docs/.nuxt 9 | rm -rf docs/.output 10 | 11 | 12 | # Theme 13 | rm -rf .nuxt 14 | rm -rf .output 15 | -------------------------------------------------------------------------------- /.github/scripts/release-edge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bump versions to edge 4 | npx jiti ./.github/scripts/bump-edge $PWD 5 | 6 | # Update token 7 | if [[ ! -z ${NODE_AUTH_TOKEN} ]] ; then 8 | echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc 9 | echo "registry=https://registry.npmjs.org/" >> ~/.npmrc 10 | echo "always-auth=true" >> ~/.npmrc 11 | echo "npmAuthToken: ${NODE_AUTH_TOKEN}" >> ~/.yarnrc.yml 12 | npm whoami 13 | fi 14 | 15 | # # Release package 16 | echo "Publishing $PWD" 17 | npm publish --access public --tolerate-republish 18 | echo "Published $PWD" 19 | -------------------------------------------------------------------------------- /.github/scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Resolve yarn 4 | YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install 5 | 6 | # Update token 7 | if [[ ! -z ${NODE_AUTH_TOKEN} ]] ; then 8 | echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc 9 | echo "registry=https://registry.npmjs.org/" >> ~/.npmrc 10 | echo "always-auth=true" >> ~/.npmrc 11 | echo "npmAuthToken: ${NODE_AUTH_TOKEN}" >> ~/.yarnrc.yml 12 | npm whoami 13 | fi 14 | 15 | # Release package 16 | echo "Publishing $PWD" 17 | # npm publish --access public --tolerate-republish 18 | echo "Published!" 19 | -------------------------------------------------------------------------------- /.github/workflows/ci-dev.yml: -------------------------------------------------------------------------------- 1 | name: ci-dev 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | pull_request: 8 | types: [opened, synchronize] 9 | branches: 10 | - dev 11 | 12 | jobs: 13 | build: 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | os: [ubuntu-latest] # macos-latest, windows-latest 19 | node: [16] 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - uses: pnpm/action-setup@v2.2.4 25 | name: Install pnpm 26 | id: pnpm-install 27 | with: 28 | version: 8 29 | 30 | - uses: actions/setup-node@v3 31 | with: 32 | node-version: ${{ matrix.node }} 33 | cache: pnpm 34 | 35 | - name: Install dependencies 36 | run: pnpm install 37 | 38 | - name: Build 39 | run: pnpm build 40 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci-main 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize] 9 | branches: 10 | - main 11 | 12 | 13 | jobs: 14 | build: 15 | runs-on: ${{ matrix.os }} 16 | 17 | strategy: 18 | matrix: 19 | os: [ubuntu-latest] # macos-latest, windows-latest 20 | node: [16] 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: pnpm/action-setup@v2.2.4 26 | name: Install pnpm 27 | id: pnpm-install 28 | with: 29 | version: 8 30 | 31 | - uses: actions/setup-node@v3 32 | with: 33 | node-version: ${{ matrix.node }} 34 | cache: pnpm 35 | 36 | - name: Install dependencies 37 | run: pnpm install 38 | 39 | - name: Build 40 | run: pnpm build 41 | -------------------------------------------------------------------------------- /.github/workflows/studio.yml: -------------------------------------------------------------------------------- 1 | 2 | name: studio-nuxt-build 3 | run-name: studio nuxt build 4 | 5 | on: 6 | # Runs on pushes targeting the default branch 7 | push: 8 | branches: ["main"] 9 | 10 | # Allows you to run this workflow manually from the Actions tab 11 | workflow_dispatch: 12 | 13 | # Add write workflow permissions 14 | permissions: 15 | contents: write 16 | 17 | # Allow one concurrent deployment 18 | concurrency: 19 | group: "pages" 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | # Build job 24 | build-and-deploy: 25 | runs-on: ${{ matrix.os }} 26 | defaults: 27 | run: 28 | working-directory: .starters/default 29 | 30 | strategy: 31 | matrix: 32 | os: [ubuntu-latest] 33 | node: [18] 34 | 35 | steps: 36 | - name: Checkout 37 | uses: actions/checkout@v4 38 | 39 | - name: Identify package manager 40 | id: pkgman 41 | run: | 42 | cache=`[ -f ".starters/default/pnpm-lock.yaml" ] && echo "pnpm" || ([ -f ".starters/default/package-lock.json" ] && echo "npm" || ([ -f ".starters/default/yarn.lock" ] && echo "yarn" || echo ""))` 43 | package_manager=`[ ! -z "$cache" ] && echo "$cache" || echo "pnpm"` 44 | echo "cache=$cache" >> $GITHUB_OUTPUT 45 | echo "package_manager=$package_manager" >> $GITHUB_OUTPUT 46 | 47 | - uses: pnpm/action-setup@v2.2.4 48 | if: ${{ steps.pkgman.outputs.package_manager == 'pnpm' }} 49 | name: Install pnpm 50 | id: pnpm-install 51 | with: 52 | version: 8 53 | 54 | - uses: actions/setup-node@v3 55 | with: 56 | version: ${{ matrix.node }} 57 | cache: ${{ steps.pkgman.outputs.cache }} 58 | 59 | - name: Install dependencies 60 | run: ${{ steps.pkgman.outputs.package_manager }} install 61 | 62 | - name: Install @nuxthq/studio 63 | run: ${{ steps.pkgman.outputs.package_manager }} add -D @nuxthq/studio 64 | 65 | - name: Create .nuxtrc 66 | run: echo 'modules[]=@nuxthq/studio' > .nuxtrc 67 | 68 | - name: Generate 69 | run: ${{ steps.pkgman.outputs.package_manager }} nuxi generate 70 | env: 71 | NUXT_PUBLIC_STUDIO_API_URL: https://api.nuxt.studio 72 | NUXT_PUBLIC_STUDIO_TOKENS: df0f47329024fc56b11978936e0e8ac1b0213ac82e47a9a1584cb5b8da096da4 73 | 74 | - name: Add .nojekyll file 75 | run: touch .output/public/.nojekyll 76 | 77 | # Deployment job 78 | - name: Deploy 🚀 79 | uses: JamesIves/github-pages-deploy-action@v4 80 | with: 81 | folder: .starters/default/.output/public 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nuxt 4 | nuxt.d.ts 5 | .output 6 | .env 7 | package-lock.json 8 | framework 9 | dist 10 | .DS_Store 11 | 12 | # Yarn 13 | .yarn/cache 14 | .yarn/*state* 15 | 16 | # Local History 17 | .history 18 | 19 | # VSCode 20 | .vscode/ 21 | tailwind.config.js.local 22 | 23 | # Starters lockfiles 24 | .starters/**/yarn.lock 25 | .starters/**/package-lock.json 26 | .starters/**/pnpm-lock.yaml 27 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | -------------------------------------------------------------------------------- /.starters/default/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@nuxt/eslint-config'], 4 | ignorePatterns: [ 5 | 'dist', 6 | 'node_modules', 7 | '.output', 8 | '.nuxt' 9 | ], 10 | rules: { 11 | 'vue/max-attributes-per-line': 'off', 12 | 'vue/multi-word-component-names': 'off' 13 | } 14 | } -------------------------------------------------------------------------------- /.starters/default/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | .output 13 | -------------------------------------------------------------------------------- /.starters/default/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.starters/default/README.md: -------------------------------------------------------------------------------- 1 | # Alpine Starter 2 | 3 | Starter template for [Alpine](https://alpine.nuxt.space). 4 | 5 | ## Clone 6 | 7 | Clone the repository (using `nuxi`): 8 | 9 | ```bash 10 | npx nuxi init -t themes/alpine 11 | ``` 12 | 13 | ## Setup 14 | 15 | Install dependencies: 16 | 17 | ```bash 18 | pnpm install 19 | ``` 20 | 21 | ## Development 22 | 23 | ```bash 24 | pnpm dev 25 | ``` 26 | 27 | ## Edge Side Rendering 28 | 29 | Can be deployed to Vercel Functions, Netlify Functions, AWS, and most Node-compatible environments. 30 | 31 | Look at all the available presets [here](https://v3.nuxtjs.org/guide/deploy/presets). 32 | 33 | ```bash 34 | pnpm build 35 | ``` 36 | 37 | ## Static Generation 38 | 39 | Use the `generate` command to build your application. 40 | 41 | The HTML files will be generated in the .output/public directory and ready to be deployed to any static compatible hosting. 42 | 43 | ```bash 44 | pnpm generate 45 | ``` 46 | 47 | ## Preview build 48 | 49 | You might want to preview the result of your build locally, to do so, run the following command: 50 | 51 | ```bash 52 | pnpm preview 53 | ``` 54 | 55 | --- 56 | 57 | For a detailed explanation of how things work, check out [Alpine](https://alpine.nuxt.space). 58 | -------------------------------------------------------------------------------- /.starters/default/app.config.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/nuxt-themes/alpine/blob/main/nuxt.schema.ts 2 | export default defineAppConfig({ 3 | alpine: { 4 | title: 'Alpine', 5 | description: 'The minimalist blog theme', 6 | image: { 7 | src: '/social-card-preview.png', 8 | alt: 'An image showcasing my project.', 9 | width: 400, 10 | height: 300 11 | }, 12 | header: { 13 | position: 'right', // possible value are : | 'left' | 'center' | 'right' 14 | logo: { 15 | path: '/logo.svg', // path of the logo 16 | pathDark: '/logo-dark.svg', // path of the logo in dark mode, leave this empty if you want to use the same logo 17 | alt: 'alpine' // alt of the logo 18 | } 19 | }, 20 | footer: { 21 | credits: { 22 | enabled: true, // possible value are : true | false 23 | repository: 'https://www.github.com/nuxt-themes/alpine' // our github repository 24 | }, 25 | navigation: true, // possible value are : true | false 26 | alignment: 'center', // possible value are : 'none' | 'left' | 'center' | 'right' 27 | message: 'Follow me on' // string that will be displayed in the footer (leave empty or delete to disable) 28 | }, 29 | socials: { 30 | twitter: 'nuxtlabs', 31 | instagram: 'atinuxt', 32 | linkedin: { 33 | icon: 'uil:linkedin', 34 | label: 'LinkedIn', 35 | href: 'https://www.linkedin.com/company/nuxtlabs' 36 | } 37 | }, 38 | form: { 39 | successMessage: 'Message sent. Thank you!' 40 | } 41 | } 42 | }) 43 | -------------------------------------------------------------------------------- /.starters/default/content/1.index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | head: 4 | title: Alpine 5 | description: An open source blog theme powered by Nuxt. 6 | title: About 7 | --- 8 | 9 | ::hero 10 | --- 11 | image: /alpine-0.webp 12 | --- 13 | #title 14 | Hi, I am Alpine. 15 | 16 | #description 17 | - An [open source blog theme](https://github.com/nuxt-themes/alpine) powered by [Nuxt Content](https://content.nuxtjs.org), editable on [Nuxt Studio](https://nuxt.studio). 18 | - Write pages in Markdown and Vue components with the [MDC syntax](https://content.nuxtjs.org/guide/writing/mdc). 19 | - Use [**30+ built-in**](https://elements.nuxt.space) components in your Markdown pages. 20 | :: 21 | 22 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. 23 | 24 | Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit. 25 | 26 | ::gallery 27 | --- 28 | images: 29 | - /alpine-0.webp 30 | - /alpine-1.webp 31 | - /alpine-2.webp 32 | --- 33 | :: 34 | -------------------------------------------------------------------------------- /.starters/default/content/2.articles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Articles 3 | layout: page 4 | --- 5 | 6 | ::articles-list{path="articles"} 7 | :: 8 | -------------------------------------------------------------------------------- /.starters/default/content/3.contact.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contact 3 | layout: default 4 | --- 5 | 6 | # Get in touch 7 | 8 | ::contact-form 9 | --- 10 | fields: 11 | - type: text 12 | name: name 13 | label: Your name 14 | required: true 15 | - type: email 16 | name: email 17 | label: Your email 18 | required: true 19 | - type: text 20 | name: subject 21 | label: Subject 22 | required: false 23 | - type: textarea 24 | name: message 25 | label: Message 26 | required: true 27 | --- 28 | :: 29 | -------------------------------------------------------------------------------- /.starters/default/content/articles/1.get-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | cover: /articles/get-started.webp 3 | author: 4 | name: Sébastien Chopin 5 | avatarUrl: https://pbs.twimg.com/profile_images/1042510623962275840/1Iw_Mvud_400x400.jpg 6 | link: https://twitter.com/atinux 7 | date: 2022-08-23T00:00:00.000Z 8 | layout: article 9 | --- 10 | 11 | # Get started with Alpine 12 | 13 | Creating a blog with Alpine is a command away, as well as deploying to many platforms. 14 | 15 | ## Create a blog 16 | 17 | Open a terminal an run the following command: 18 | 19 | ```bash 20 | npx nuxi@latest init -t themes/alpine 21 | ``` 22 | 23 | ## Dependencies 24 | 25 | Next, go to to `my-blog/` directory and install the dependencies: 26 | 27 | ```bash 28 | npm install 29 | ``` 30 | 31 | ## Development 32 | 33 | Start the development server on port 3000: 34 | 35 | ```bash 36 | npm run dev 37 | ``` 38 | 39 | Next, you can start creating your content in Markdown in the `content/` directory. 40 | 41 | ## Deploy 42 | 43 | ### Static hosting 44 | 45 | You can deploy Alpine to any static hosting by running the following command: 46 | 47 | ```bash 48 | npm run generate 49 | ``` 50 | 51 | This command will create a `dist/` directory with the compiled files ready to be uploaded to any static hosting. 52 | 53 | ### Edge platforms 54 | 55 | Alpine supports deploying to the following platforms with **zero configuration**: 56 | 57 | - [Vercel](https://vercel.com) 58 | - [Netlify](https://netlify.com) 59 | - [and more...](https://v3.nuxtjs.org/guide/deploy/presets#supported-hosting-providers) 60 | 61 | ### Node server 62 | 63 | You can deploy Alpine to a Node server by running the following command: 64 | 65 | ```bash 66 | npm run build 67 | ``` 68 | 69 | This command will create a `.output/` directory with the compiled files ready to be uploaded to any Node server. 70 | 71 | To start the production server, run the following command: 72 | 73 | ```bash 74 | node .output/server/index.mjs 75 | ``` 76 | -------------------------------------------------------------------------------- /.starters/default/content/articles/2.configure.md: -------------------------------------------------------------------------------- 1 | --- 2 | cover: /articles/configure-alpine.webp 3 | author: 4 | name: Clément Ollivier 5 | avatarUrl: https://pbs.twimg.com/profile_images/1370286658432724996/ZMSDzzIi_400x400.jpg 6 | link: https://twitter.com/clemcodes 7 | date: 2022-08-23T00:00:00.000Z 8 | description: Learn how to configure Alpine with the app.config.ts file. 9 | layout: article 10 | --- 11 | 12 | # Configure Alpine 13 | 14 | To configure meta tags, social links or even the Alpine theme display, update the `alpine` key in the `app.config.ts` at the root of your project: 15 | 16 | ```ts [app.config.ts] 17 | export default defineAppConfig({ 18 | alpine: { 19 | /* Alpine configuration goes here */ 20 | } 21 | } 22 | ``` 23 | 24 | You can look at the [default config](https://github.com/nuxt-themes/alpine/tree/main/app.config.ts). 25 | 26 | The [config schema](https://github.com/nuxt-themes/alpine/tree/main/app.config.ts) also gives comments on all the configuration parameters. 27 | 28 | ## Meta tags 29 | 30 | Configure the title, description and social image of your website: 31 | 32 | ```ts [app.config.ts] 33 | export default defineAppConfig({ 34 | alpine: { 35 | title: 'Alpine', 36 | description: 'The minimalist blog theme', 37 | image: '/social-card-preview.png', 38 | // image can also be an object: 39 | image: { 40 | src: '/social-card-preview.png', 41 | alt: 'An image showcasing my project.', 42 | width: 400, 43 | height: 300 44 | } 45 | } 46 | }) 47 | ``` 48 | 49 | ## Social links 50 | 51 | To configure the social links displayed in the footer, use the `socials` property: 52 | 53 | ```ts [app.config.ts] 54 | export default defineAppConfig({ 55 | alpine: { 56 | socials: { 57 | twitter: 'nuxtlabs', 58 | instagram: 'wearenuxt', 59 | linkedin: { 60 | icon: 'uil:linkedin', 61 | label: 'LinkedIn', 62 | href: 'https://www.linkedin.com/company/nuxtlabs' 63 | }, 64 | mastodon: { 65 | icon: 'simple-icons:mastodon', 66 | label: 'Mastodon', 67 | href: 'https://m.webtoo.ls/@nuxt', 68 | rel: 'me' 69 | } 70 | } 71 | } 72 | }) 73 | ``` 74 | 75 | ## Theme display 76 | 77 | Alpine Header and Footer can also be customized via the `app.config.ts` file: 78 | 79 | ```ts [app.config.ts] 80 | defineAppConfig({ 81 | alpine: { 82 | // Remove header with header: false 83 | header: { 84 | position: 'inline', // possible value are : 'none' | 'left' | 'center' | 'right' | 'inline' 85 | logo: false 86 | }, 87 | // Remove header with footer: false 88 | footer: { 89 | credits: { 90 | enabled: true, // possible value are : true | false 91 | repository: 'https://www.github.com/nuxt-themes/alpine' // our github repository 92 | }, 93 | navigation: false, // possible value are : true | false 94 | position: 'center', // possible value are : 'none' | 'left' | 'center' | 'right' 95 | message: 'Follow me on' // string that will be displayed on the footer (leave empty or delete to disable) 96 | } 97 | // Disable back to top button: false 98 | backToTop: { 99 | text: 'Back to top', 100 | icon: 'material-symbols:arrow-upward' 101 | } 102 | } 103 | }) 104 | ``` 105 | -------------------------------------------------------------------------------- /.starters/default/content/articles/3.write-articles.md: -------------------------------------------------------------------------------- 1 | --- 2 | cover: /articles/write-articles.webp 3 | date: 2022-08-23T00:00:00.000Z 4 | description: Writing Markdown articles in Alpine is straightforward. 5 | layout: article 6 | --- 7 | 8 | # Write Articles 9 | 10 | Write Markdown articles in Alpine is straightforward. 11 | 12 | ## Create an articles list 13 | 14 | Create a new file in the `content/` directory: 15 | 16 | ```bash 17 | touch content/2.articles.md 18 | ``` 19 | 20 | The numbered prefix determines the order of the menu items. 21 | 22 | In this file, use the `articles-list` component to display the list of articles: 23 | 24 | ```md [2.articles.md] 25 | --- 26 | title: 'Articles' 27 | layout: 'page' 28 | --- 29 | ::articles-list 30 | --- 31 | path: articles 32 | --- 33 | :: 34 | ``` 35 | 36 | The `path` prop corresponds to the directory where the articles are stored. 37 | 38 | ## Display an article in the list 39 | 40 | Create a new file in the `/content/articles` directory: 41 | 42 | ```bash 43 | mkdir content/articles 44 | touch content/articles/1.my-new-article.md 45 | ``` 46 | 47 | For your article to be correctly displayed in the [articles list](/articles), define a `cover` and `date` property in the frontmatter: 48 | 49 | ```yaml [content/articles/1.my-new-article.md] 50 | --- 51 | cover: path/to/cover 52 | date: 2022-08-23 53 | --- 54 | ``` 55 | 56 | The `cover` property can be a local path relative to the `/public` directory or an external URL. 57 | 58 | Your article will now be displayed in the list with its filename as a default title. 59 | 60 | ## Edit your article 61 | 62 | Under the frontmatter block, enter a Markdown `h1` tag and a line of text: 63 | 64 | ```md [content/articles/1.my-new-article.md] 65 | --- 66 | cover: path/to/cover 67 | date: 2022-08-23 68 | --- 69 | # An awesome article 70 | This article is little by size but big by heart. 71 | ``` 72 | 73 | Your article will now be displayed in the list with the title and description you wrote in Markdown. 74 | 75 | ## Override title and description 76 | 77 | If you want to change the title and description displayed on the list and in the meta tags of the article, add the `title` and `description` property to your frontmatter: 78 | 79 | ```md [content/articles/1.my-new-article.md] 80 | --- 81 | cover: path/to/cover 82 | date: 2022-08-23 83 | title: Another title 84 | description: Another description 85 | --- 86 | ``` 87 | 88 | You are now ready to edit your article and create new ones! 89 | 90 | ## Optional Arguments 91 | 92 | In the frontmatter block, you can pass additional options for displaying your article, such as displaying badges on the image: 93 | 94 | ```md 95 | --- 96 | cover: path/to/cover 97 | date: 2022-08-23 98 | badges: [{ 99 | color: 'white', 100 | bg: 'rgba(0, 0, 0, 0.3)', 101 | content: 'Technology' 102 | }] 103 | --- 104 | ``` 105 | 106 | ## Read more 107 | 108 | Alpine is a Nuxt theme using the Content module in `documentDriven` mode. 109 | 110 | 👉 Learn more in the [Nuxt Content documentation](https://content.nuxtjs.org/). 111 | -------------------------------------------------------------------------------- /.starters/default/content/articles/4.design-tokens.md: -------------------------------------------------------------------------------- 1 | --- 2 | cover: /articles/design-tokens.webp 3 | date: 2022-08-23T00:00:00.000Z 4 | layout: article 5 | --- 6 | 7 | # Customize Alpine 8 | 9 | Leverage the `tokens.config.ts` to give your identity to Alpine. 10 | 11 | Look at the [default tokens config](https://github.com/nuxt-themes/alpine/blob/main/tokens.config.ts) to check all the Alpine related Design Tokens. 12 | 13 | Alpine is also powered by [@nuxt-themes/tokens](https://www.npmjs.com/package/@nuxt-themes/tokens), see the [package tokens.config.ts](https://unpkg.com/@nuxt-themes/tokens@latest/dist/tokens.config.ts). 14 | 15 | You can configure all the theme tokens to change the apperance of Alpine by creating a `tokens.config.ts` in your project: 16 | 17 | ```ts 18 | import { defineTheme } from 'pinceau' 19 | 20 | export default defineTheme({ 21 | alpine: { 22 | body: { 23 | // Update the background color in light & dark mode 24 | backgroundColor: { 25 | initial: '#f8fafc', 26 | dark: '#0f172a' 27 | } 28 | } 29 | } 30 | }) 31 | ``` 32 | 33 | If you are using [Nuxt Studio](https://nuxt.studio), you can use an UI to update the `token.config.ts` of your Alpine project: 34 | 35 | [![design-tokens-studio.png](/design-tokens-studio.png)](https://nuxt.studio) 36 | -------------------------------------------------------------------------------- /.starters/default/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | // https://github.com/nuxt-themes/alpine 3 | extends: '@nuxt-themes/alpine', 4 | 5 | modules: [ 6 | // https://github.com/nuxt-modules/plausible 7 | '@nuxtjs/plausible', 8 | // https://github.com/nuxt/devtools 9 | '@nuxt/devtools' 10 | ] 11 | }) 12 | -------------------------------------------------------------------------------- /.starters/default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpine-starter", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "generate": "nuxi generate", 9 | "preview": "nuxi preview", 10 | "lint": "eslint ." 11 | }, 12 | "devDependencies": { 13 | "@nuxt-themes/alpine": "latest", 14 | "@nuxt/devtools": "^1.0.8", 15 | "@nuxt/eslint-config": "^0.2.0", 16 | "@nuxtjs/plausible": "^0.2.4", 17 | "@types/node": "^20.11.24", 18 | "eslint": "^8.57.0", 19 | "nuxt": "^3.10.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.starters/default/public/alpine-0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/alpine-0.webp -------------------------------------------------------------------------------- /.starters/default/public/alpine-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/alpine-1.webp -------------------------------------------------------------------------------- /.starters/default/public/alpine-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/alpine-2.webp -------------------------------------------------------------------------------- /.starters/default/public/articles/configure-alpine.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/articles/configure-alpine.webp -------------------------------------------------------------------------------- /.starters/default/public/articles/design-tokens.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/articles/design-tokens.webp -------------------------------------------------------------------------------- /.starters/default/public/articles/get-started.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/articles/get-started.webp -------------------------------------------------------------------------------- /.starters/default/public/articles/write-articles.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/articles/write-articles.webp -------------------------------------------------------------------------------- /.starters/default/public/design-tokens-studio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/design-tokens-studio.png -------------------------------------------------------------------------------- /.starters/default/public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.starters/default/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.starters/default/public/social-card-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clemcode/alpine-theme/ff4602b87e3f7e773a7becd60cf60356fd88369b/.starters/default/public/social-card-preview.png -------------------------------------------------------------------------------- /.starters/default/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>nuxt/renovate-config-nuxt"], 3 | "lockFileMaintenance": { 4 | "enabled": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.starters/default/tokens.config.ts: -------------------------------------------------------------------------------- 1 | import { defineTheme } from 'pinceau' 2 | 3 | export default defineTheme({ 4 | }) 5 | -------------------------------------------------------------------------------- /.starters/default/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 NuxtLabs SAS 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 | [![Alpine](./.starters/default/public/social-card-preview.png)](https://alpine.nuxt.space) 2 | 3 | # Alpine 4 | 5 | [![npm version][npm-version-src]][npm-version-href] 6 | [![License][license-src]][license-href] 7 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 8 | [![Nuxt][nuxt-src]][nuxt-href] 9 | [![Nuxt Studio][nuxt-studio-src]][nuxt-studio-href] 10 | [![Volta][volta-src]][volta-href] 11 | 12 | The minimalist blog theme, powered by [Nuxt](https://nuxt.com). 13 | 14 | 15 | - [📸 Online demo](https://alpine.nuxt.space) 16 | - [⚡️ Play on StackBlitz](https://stackblitz.com/github/nuxt-themes/alpine-starter) 17 | 18 | ## Features 19 | 20 | - Start from a **profile page**, scale to a **complete blog**! 21 | - An [open source blog theme](https://github.com/nuxt-themes/alpine) powered by [Nuxt Content](https://content.nuxtjs.org), editable from [Nuxt Studio](https://nuxt.studio). 22 | - Write pages in Markdown and Vue components with the [MDC syntax](https://content.nuxtjs.org/guide/writing/mdc). 23 | - Use [**30+ built-in**](https://elements.nuxt.space) components in your Markdown pages. 24 | 25 | ## Quick Start 26 | 27 | ```bash 28 | npx nuxi@latest init -t themes/alpine 29 | ``` 30 | 31 | ## Contributing 🙏 32 | 33 | 1. Clone this repository 34 | 2. Install dependencies using `pnpm install` 35 | 3. Run `pnpm prepare` to generate type stubs. 36 | 4. Use `pnpm dev` to start [playground](./playground) in development mode. 37 | 38 | ## License 39 | 40 | [MIT](./LICENSE) 41 | 42 | 43 | [npm-version-src]: https://img.shields.io/npm/v/@nuxt-themes/alpine/latest.svg?style=flat&colorA=18181B&colorB=28CF8D 44 | [npm-version-href]: https://npmjs.com/package/@nuxt-themes/alpine 45 | 46 | [npm-downloads-src]: https://img.shields.io/npm/dt/@nuxt-themes/alpine.svg?style=flat&colorA=18181B&colorB=28CF8D 47 | [npm-downloads-href]: https://npmjs.com/package/@nuxt-themes/alpine 48 | 49 | [license-src]: https://img.shields.io/github/license/nuxt-themes/alpine.svg?style=flat&colorA=18181B&colorB=28CF8D 50 | [license-href]: https://github.com/nuxt-themes/alpine/blob/main/LICENSE 51 | 52 | 53 | [nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?&logo=nuxt.js 54 | [nuxt-href]: https://nuxt.com 55 | 56 | [nuxt-studio-src]: https://img.shields.io/badge/Open%20in%20Nuxt%20Studio-18181B?&logo=nuxt.js&logoColor=3BB5EC 57 | [nuxt-studio-href]: https://nuxt.studio/themes/alpine 58 | 59 | [volta-src]: https://user-images.githubusercontent.com/904724/209143798-32345f6c-3cf8-4e06-9659-f4ace4a6acde.svg 60 | [volta-href]: https://volta.net/nuxt-themes/alpine?utm_source=readme_alpine 61 | -------------------------------------------------------------------------------- /app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | alpine: { 3 | title: 'Alpine', 4 | description: 'The minimalist blog theme', 5 | image: { 6 | src: '/social-card-preview.png', 7 | alt: 'An image showcasing my project.', 8 | width: 400, 9 | height: 300 10 | }, 11 | header: { 12 | position: 'right', 13 | logo: { 14 | path: '/logo.svg', 15 | pathDark: '/logo-dark.svg', 16 | alt: 'alpine' 17 | } 18 | }, 19 | footer: { 20 | credits: { 21 | enabled: true, 22 | text: 'Alpine', 23 | repository: 'https://www.github.com/nuxt-themes/alpine' 24 | }, 25 | navigation: true, 26 | alignment: 'center', 27 | message: 'Follow me on' 28 | }, 29 | socials: { 30 | twitter: '', 31 | instagram: '', 32 | github: '', 33 | facebook: '', 34 | medium: '', 35 | youtube: '' 36 | }, 37 | form: { 38 | successMessage: 'Message sent. Thank you!' 39 | }, 40 | backToTop: { 41 | text: 'Back to top', 42 | icon: 'material-symbols:arrow-upward' 43 | } 44 | } 45 | }) 46 | -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /assets/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: $dt('alpine.body.backgroundColor'); 3 | color: $dt('alpine.body.color'); 4 | } 5 | 6 | /* Color scheme images helper classes */ 7 | .light-img { 8 | display: block; 9 | } 10 | .dark-img { 11 | display: none; 12 | } 13 | @dark { 14 | .dark-img { 15 | display: block; 16 | } 17 | .light-img { 18 | display: none; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/AppFooter.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 33 | 34 | 111 | -------------------------------------------------------------------------------- /components/AppHeader.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 40 | 41 | 152 | -------------------------------------------------------------------------------- /components/AppLayout.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 28 | 29 | -------------------------------------------------------------------------------- /components/AppLoadingBar.vue: -------------------------------------------------------------------------------- 1 | 81 | 82 | 97 | 98 | 111 | -------------------------------------------------------------------------------- /components/Button.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 20 | 47 | -------------------------------------------------------------------------------- /components/ColorModeSwitch.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 30 | 31 | 48 | -------------------------------------------------------------------------------- /components/DocumentDrivenNotFound.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /components/MainNav.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 29 | 30 | 65 | -------------------------------------------------------------------------------- /components/SocialIcons.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 52 | 53 | 71 | -------------------------------------------------------------------------------- /components/content/ArticlesList.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 35 | 36 | 73 | -------------------------------------------------------------------------------- /components/content/ArticlesListItem.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 81 | 82 | 150 | -------------------------------------------------------------------------------- /components/content/ContactForm.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 109 | 110 | 124 | -------------------------------------------------------------------------------- /components/content/Gallery.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | 28 | 50 | -------------------------------------------------------------------------------- /components/content/Hero.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 44 | 45 | 78 | -------------------------------------------------------------------------------- /components/data-entry/Input.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 |