feat: bootstrap Nuxt portfolio with Tailwind and daisyUI for now

This commit is contained in:
badblocks 2025-07-17 15:53:12 -07:00
commit 91b162fb44
No known key found for this signature in database
15 changed files with 3363 additions and 0 deletions

25
.gitignore vendored Normal file
View file

@ -0,0 +1,25 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist
# Node dependencies
node_modules
# Logs
logs
*.log
# Misc
.DS_Store
.fleet
.idea
public/headshot_pp.png
# Local env files
.env
.env.*
!.env.example

75
README.md Normal file
View file

@ -0,0 +1,75 @@
# Nuxt Minimal Starter
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
## Setup
Make sure to install dependencies:
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
```
## Development Server
Start the development server on `http://localhost:3000`:
```bash
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
```
## Production
Build the application for production:
```bash
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
```
Locally preview production build:
```bash
# npm
npm run preview
# pnpm
pnpm preview
# yarn
yarn preview
# bun
bun run preview
```
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.

69
app/app.vue Normal file
View file

@ -0,0 +1,69 @@
<template>
<UApp>
<div data-theme="night">
<main>
<!-- The content of the current page will be rendered here -->
<NuxtPage />
</main>
<!-- Footer -->
<footer class="footer p-10 bg-base-300 text-base-content">
<div>
<span class="footer-title">Social</span>
<div class="grid grid-flow-col gap-4">
<a
><svg
role="img"
width="24"
height="24"
class="fill-current"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z"
/></svg
></a>
<a
><svg
role="img"
width="24"
height="24"
class="fill-current"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
/></svg
></a>
<a
><svg
role="img"
width="24"
height="24"
class="fill-current"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.7773 0c1.6018 0 2.9004 1.2986 2.9004 2.9005s-1.2986 2.9004-2.9004 2.9004c-1.0854 0-2.0315-.596-2.5288-1.4787H12.91c-2.3322 0-4.2272 1.8718-4.2649 4.195l-.0007 2.1175a7.0759 7.0759 0 0 1 4.148-1.4205l.1176-.001 1.3385.0002c.4973-.8827 1.4434-1.4788 2.5288-1.4788 1.6018 0 2.9004 1.2986 2.9004 2.9005s-1.2986 2.9004-2.9004 2.9004c-1.0854 0-2.0315-.596-2.5288-1.4787H12.91c-2.3322 0-4.2272 1.8718-4.2649 4.195l-.0007 2.319c.8827.4973 1.4788 1.4434 1.4788 2.5287 0 1.602-1.2986 2.9005-2.9005 2.9005-1.6018 0-2.9004-1.2986-2.9004-2.9005 0-1.0853.596-2.0314 1.4788-2.5287l-.0002-9.9831c0-3.887 3.1195-7.0453 6.9915-7.108l.1176-.001h1.3385C14.7458.5962 15.692 0 16.7773 0ZM7.2227 19.9052c-.6596 0-1.1943.5347-1.1943 1.1943s.5347 1.1943 1.1943 1.1943 1.1944-.5347 1.1944-1.1943-.5348-1.1943-1.1944-1.1943Zm9.5546-10.4644c-.6596 0-1.1944.5347-1.1944 1.1943s.5348 1.1943 1.1944 1.1943c.6596 0 1.1943-.5347 1.1943-1.1943s-.5347-1.1943-1.1943-1.1943Zm0-7.7346c-.6596 0-1.1944.5347-1.1944 1.1943s.5348 1.1943 1.1944 1.1943c.6596 0 1.1943-.5347 1.1943-1.1943s-.5347-1.1943-1.1943-1.1943Z"
/></svg
></a>
</div>
</div>
<div>
<p>Copyright © {{ new Date().getFullYear() }}</p>
</div>
</footer>
</div>
</UApp>
</template>
<script setup>
/* Global */
</script>
<style>
/* Global */
</style>

3
app/assets/css/main.css Normal file
View file

@ -0,0 +1,3 @@
@import "tailwindcss";
@import "@nuxt/ui";
@plugin "daisyui";

220
app/pages/index.vue Normal file
View file

@ -0,0 +1,220 @@
<template>
<div>
<!-- Hero Section -->
<section class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold">
Hi, I'm <span class="text-primary">Rob</span>!
</h1>
<p class="py-6 text-2xl">I'm <span id="typed-text"></span></p>
<button class="btn btn-primary">View My Work</button>
</div>
</div>
</section>
<!-- About Me Section -->
<section id="about" class="py-20 bg-base-100">
<div class="container mx-auto px-4">
<h2 class="text-4xl font-bold text-center mb-12">About Me</h2>
<div
class="flex flex-col md:flex-row items-center justify-center gap-10"
>
<div class="md:w-1/3 text-center">
<div class="avatar">
<div
class="w-48 rounded-full ring ring-primary ring-offset-base-100 ring-offset-2"
>
<img src="/headshot_pp.png" alt="Rob" />
</div>
</div>
</div>
<div class="md:w-2/3">
<p class="text-lg mb-4">
Hello! I'm a passionate and creative junior web developer with a
knack for building beautiful and functional websites. I love
learning new technologies and I'm always looking for exciting
projects to work on.
</p>
<h3 class="text-2xl font-bold mb-4">My Skills</h3>
<div class="flex flex-wrap gap-4">
<div class="badge badge-primary badge-lg">HTML</div>
<div class="badge badge-primary badge-lg">CSS</div>
<div class="badge badge-primary badge-lg">JavaScript</div>
<div class="badge badge-primary badge-lg">Git</div>
<div class="badge badge-primary badge-lg">Nuxt.js</div>
<div class="badge badge-primary badge-lg">Tailwind CSS</div>
<div class="badge badge-primary badge-lg">Docker</div>
<div class="badge badge-primary badge-lg">Node/Bun</div>
</div>
</div>
</div>
</div>
</section>
<!-- Projects Section -->
<section id="projects" class="py-20 bg-base-200">
<div class="container mx-auto px-4">
<h2 class="text-4xl font-bold text-center mb-12">My Projects</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Project Card 1 -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Project One</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">Live Demo</button>
<button class="btn btn-secondary">Source Code</button>
</div>
</div>
</div>
<!-- Project Card 2 -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Project Two</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">Live Demo</button>
<button class="btn btn-secondary">Source Code</button>
</div>
</div>
</div>
<!-- Project Card 3 -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Project Three</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">Live Demo</button>
<button class="btn btn-secondary">Source Code</button>
</div>
</div>
</div>
<!-- Project Card 4 -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Project Four</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">Live Demo</button>
<button class="btn btn-secondary">Source Code</button>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="py-20 bg-base-100">
<div class="container mx-auto px-4">
<h2 class="text-4xl font-bold text-center mb-12">Get In Touch</h2>
<div class="max-w-xl mx-auto">
<form>
<div class="form-control mb-4">
<input
type="text"
placeholder="Your Name"
aria-label="Your Name"
class="input input-bordered w-full"
/>
</div>
<div class="flex flex-col md:flex-row gap-4 mb-4">
<div class="form-control w-full md:w-1/2">
<div class="join w-full">
<input
type="tel"
placeholder="Your Phone Number"
aria-label="Your Phone Number"
class="input input-bordered w-full"
/>
<button class="btn btn-secondary join-item">Send Code</button>
</div>
</div>
<div class="form-control w-full md:w-1/2">
<div class="join w-full">
<input
type="text"
placeholder="Verification Code"
aria-label="Verification Code"
class="input input-bordered join-item w-full"
/>
<button class="btn btn-secondary join-item">Verify</button>
</div>
</div>
</div>
<div class="form-control mb-4">
<textarea
class="textarea textarea-bordered h-32 w-full"
placeholder="Your message..."
aria-label="Your message..."
></textarea>
</div>
<div class="text-center">
<button class="btn btn-primary w-full">Text Me!</button>
</div>
</form>
</div>
</div>
</section>
</div>
</template>
<script setup>
import { onMounted } from "vue";
import Typed from "typed.js";
onMounted(() => {
const { $sr } = useNuxtApp();
const typedOptions = {
strings: [
"an aspiring Software Engineer.",
"a Web Developer.",
"a Backend Magician.",
"a UI/UX Problem Solver.",
"an Accessibility Advocate.",
"an Open Source Contributor.",
"a Collaborative Teammate.",
"a Creative Coder.",
],
typeSpeed: 60,
backSpeed: 40,
loop: true,
cursorChar: "|",
};
new Typed("#typed-text", typedOptions);
$sr.reveal(".hero h1", { delay: 200 });
$sr.reveal(".hero p", { delay: 400 });
$sr.reveal(".hero .btn", { delay: 600 });
$sr.reveal("#about h2, #projects h2, #contact h2", { delay: 200 });
$sr.reveal("#about .avatar", { origin: "left", delay: 300 });
$sr.reveal("#about .md\\:w-2\\/3", { origin: "right", delay: 400 });
$sr.reveal("#projects .card", { interval: 100 });
$sr.reveal("#contact form", { delay: 300 });
});
</script>
<style>
/* Ensuring the hero section takes the full viewport height */
.min-h-screen {
min-height: 100vh;
}
</style>

View file

@ -0,0 +1,19 @@
import ScrollReveal from 'scrollreveal';
export default defineNuxtPlugin((nuxtApp) => {
const defaultOptions = {
origin: 'bottom',
distance: '80px',
duration: 1000,
delay: 200,
easing: 'cubic-bezier(0.5, 0, 0, 1)',
reset: true,
};
const sr = ScrollReveal(defaultOptions);
// You can make it available to the rest of your Nuxt application
// by returning it in the `provide` object.
// This makes it accessible as `$sr` in your components.
nuxtApp.provide('sr', sr);
});

2853
bun.lock Normal file

File diff suppressed because it is too large Load diff

6
eslint.config.mjs Normal file
View file

@ -0,0 +1,6 @@
// @ts-check
import withNuxt from '.nuxt/eslint.config.mjs'
export default withNuxt(
// Your custom configs here
)

22
nuxt.config.ts Normal file
View file

@ -0,0 +1,22 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: "2025-05-15",
devtools: {
enabled: true,
timeline: {
enabled: true,
},
},
css: ["assets/css/main.css"],
modules: [
"@nuxt/content",
"@nuxt/eslint",
"@nuxt/fonts",
"@nuxt/icon",
"@nuxt/image",
"@nuxt/scripts",
"@nuxt/test-utils",
"@nuxt/ui",
],
});

44
package.json Normal file
View file

@ -0,0 +1,44 @@
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@nuxt/content": "3.6.3",
"@nuxt/eslint": "1.5.2",
"@nuxt/fonts": "0.11.4",
"@nuxt/icon": "1.15.0",
"@nuxt/image": "1.10.0",
"@nuxt/scripts": "0.11.9",
"@nuxt/test-utils": "3.19.2",
"@nuxt/ui": "3.2.0",
"@unhead/vue": "^2.0.3",
"android-sms-gateway": "^3.0.0",
"better-sqlite3": "^12.2.0",
"daisyui": "^5.0.46",
"eslint": "^9.0.0",
"husky": "^9.1.7",
"nuxt": "^4.0.0",
"postcss": "^8.5.6",
"scrollreveal": "^4.0.9",
"typed.js": "^2.1.0",
"typescript": "^5.6.3",
"vue": "^3.5.17",
"vue-router": "^4.5.1"
},
"trustedDependencies": [
"@parcel/watcher",
"@tailwindcss/oxide",
"better-sqlite3",
"esbuild",
"scrollreveal",
"sharp",
"vue-demi"
]
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

2
public/robots.txt Normal file
View file

@ -0,0 +1,2 @@
User-Agent: *
Disallow:

3
server/tsconfig.json Normal file
View file

@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

18
tailwind.config.js Normal file
View file

@ -0,0 +1,18 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./components/**/*.{js,vue,ts}",
"./layouts/**/*.vue",
"./pages/**/*.vue",
"./plugins/**/*.{js,ts}",
"./nuxt.config.{js,ts}",
"./app.vue",
],
theme: {
extend: {},
},
plugins: [require("daisyui")],
daisyui: {
themes: ["night", "bumblebee"],
},
};

4
tsconfig.json Normal file
View file

@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}