Compare commits

...

2 Commits

Author SHA1 Message Date
Keith Irwin 3d0a2447ac
Tried to get serverless to work 2023-03-02 15:35:21 -07:00
Keith Irwin 537e7c9b9c
Moved everything to single dir 2023-03-02 12:09:55 -07:00
190 changed files with 377 additions and 345 deletions

View File

@ -1,11 +1,9 @@
# Dev
SITE_DOMAIN="http://localhost:8080"
API_DOMAIN="http://localhost:8081"
DOMAIN="http://localhost:8080"
STRIPE_SEC="sk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
STRIPE_PUB="pk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Production
#SITE_DOMAIN="https://www.example.com"
#API_DOMAIN="https://api.example.com"
#DOMAIN="https://www.example.com"
#STRIPE_PUB="pk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#STRIPE_SEC="sk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

19
.gitignore vendored
View File

@ -1,20 +1,17 @@
# node.js installs
# Packages
**/node_modules/
**/package-lock.json
# environment
# Environment
.env
docker-compose.yml
data/
_src/_data/
# frontend build
site/_site/
# Build
_site/
_functions/dynamic/**
!_functions/dynamic/index.js
# aspell backups
# Backups and tempfiles
**/*.bak
# vim swaps
**/*.swp
# https://www.11ty.dev/docs/plugins/serverless/
site/functions/serverless/**
!site/functions/serverless/index.js

View File

@ -1,9 +1,77 @@
# eleventy-base-blog
# Shopity
A starter repository showing how to build a blog with the [Eleventy](https://github.com/11ty/eleventy) static site generator.
Ecommerce template using 11ty, knockout, stripe, docker
[![Build Status](https://travis-ci.org/11ty/eleventy-base-blog.svg?branch=master)](https://travis-ci.org/11ty/eleventy-base-blog)
## Setting shipping rates data
## Demos
- **zips-to-zones:** [USPS Zone chart by zip code](https://postcalc.usps.com/DomesticZoneChart)
- **usps-shipping-rates:** [USPS Rates by zone/weight](https://pe.usps.com/text/dmm300/Notice123.htm#_c078)
* [Netlify](https://eleventy-base-blog.netlify.com/)
* [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
* [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
## Deploy this to your own site
These builders are amazing—try them out to get your own Eleventy site in a few clicks!
* [Get your own Eleventy web site on Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)
* [Get your own Eleventy web site on Vercel](https://vercel.com/import/project?template=11ty%2Feleventy-base-blog)
## Getting Started
### 1. Clone this Repository
```
git clone https://github.com/11ty/eleventy-base-blog.git my-blog-name
```
### 2. Navigate to the directory
```
cd my-blog-name
```
Specifically have a look at `.eleventy.js` to see if you want to configure any Eleventy options differently.
### 3. Install dependencies
```
npm install
```
### 4. Edit _data/metadata.json
### 5. Run Eleventy
```
npx eleventy
```
Or build and host locally for local development
```
npx eleventy --serve
```
Or build automatically when a template changes:
```
npx eleventy --watch
```
Or in debug mode:
```
DEBUG=* npx eleventy
```
### Implementation Notes
* `about/index.md` shows how to add a content page.
* `posts/` has the blog posts but really they can live in any directory. They need only the `post` tag to be added to this collection.
* Add the `nav` tag to add a template to the top level site navigation. For example, this is in use on `index.njk` and `about/index.md`.
* Content can be any template format (blog posts neednt be markdown, for example). Configure your supported templates in `.eleventy.js` -> `templateFormats`.
* Because `css` and `png` are listed in `templateFormats` but are not supported template types, any files with these extensions will be copied without modification to the output (while keeping the same directory structure).
* The blog post feed template is in `feed/feed.njk`. This is also a good example of using a global data files in that it uses `_data/metadata.json`.
* This example uses three layouts:
* `_includes/layouts/base.njk`: the top level HTML structure
* `_includes/layouts/post.njk`: the blog post template (wrapped into `base.njk`)
* `_includes/postlist.njk` is a Nunjucks include and is a reusable component used to display a list of all the posts. `index.njk` has an example of how to use it.

View File

@ -0,0 +1,57 @@
const { EleventyServerless } = require("@11ty/eleventy");
// Explicit dependencies for the bundler from config file and global data.
// The file is generated by the Eleventy Serverless Bundler Plugin.
require("./eleventy-bundler-modules.js");
async function handler(event) {
let elev = new EleventyServerless("dynamic", {
path: new URL(event.rawUrl).pathname,
query: event.multiValueQueryStringParameters || event.queryStringParameters,
functionsDir: "_functions",
});
try {
let [page] = await elev.getOutput();
// If you want some of the data cascade available in `page.data`, use `eleventyConfig.dataFilterSelectors`.
// Read more: https://www.11ty.dev/docs/config/#data-filter-selectors
return {
statusCode: 200,
headers: {
"Content-Type": "text/html; charset=UTF-8",
},
body: page.content,
};
} catch (error) {
// Only console log for matching serverless paths
// (otherwise youll see a bunch of BrowserSync 404s for non-dynamic URLs during --serve)
if (elev.isServerlessUrl(event.path)) {
console.log("Serverless Error:", error);
}
return {
statusCode: error.httpStatusCode || 500,
body: JSON.stringify(
{
error: error.message,
},
null,
2
),
};
}
}
// Choose one:
// * Runs on each request: AWS Lambda, Netlify Function
// * Runs on first request only: Netlify On-demand Builder
// 1. Dont forget to `npm install @netlify/functions`
// 2. Also use `redirects: "netlify-toml-builders"` in your config files serverless bundler options:
// https://www.11ty.dev/docs/plugins/serverless/#bundler-options
exports.handler = handler;
//const { builder } = require("@netlify/functions");
//exports.handler = builder(handler);

View File

@ -0,0 +1,12 @@
---
permalink: /assets/data/products.json
---
{
{%- for prod in collections.products %}
"{{prod.data.pid}}/{{prod.data.sid}}": {
"price": {{prod.data.price|dump|safe}},
"weight": {{prod.data.specs.weight|dump|safe}},
"volume": {{prod.data.specs.dimensions|dimsToVol|dump|safe}}
}{% if loop.index!==loop.length %},{% endif %}
{%- endfor %}
}

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View File

Before

Width:  |  Height:  |  Size: 495 B

After

Width:  |  Height:  |  Size: 495 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

Before

Width:  |  Height:  |  Size: 879 B

After

Width:  |  Height:  |  Size: 879 B

View File

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 507 B

View File

@ -192,11 +192,11 @@ class Cart { constructor() {
)
self.checkoutButtonText = ko.pureComputed(() => {
if (self.isLoading())
return '📃 Creating order...'
return 'Checking out...'
else if (self.subtotal()>0)
return `📃 Create order for ${self.total_pretty()}`
return `Checkout for ${self.total_pretty()}`
else
return '📃 Create order'
return 'Checkout'
})
self.checkoutButtonHelp = ko.pureComputed(() => {
if (self.total()===0) return 'Add items to your cart first'
@ -247,17 +247,17 @@ class Cart { constructor() {
if (self.payment_method()==='USD') {
// Send to server
const res = await fetch(`${API_DOMAIN}/order`, {
method: 'POST', mode: 'cors',
headers: {'Content-Type':'application/json'},
body: ko.toJSON(order),
})
localStorage.setItem('order_data', await res.json())
//const res = await fetch('/shop/checkout/order', {
// method: 'POST', mode: 'cors',
// headers: {'Content-Type':'application/json'},
// body: ko.toJSON(order),
//})
//localStorage.setItem('order_data', await res.json())
// Send user to checkout
window.location = '/shop/checkout/stripe/'
} else self.isLoading(false)
}
// On first load, read from localStorage
Object.keys(localStorage).forEach(i => {
if (i.substring(0,5)==='cart_') {

View File

@ -1,6 +1,5 @@
const formatUSD = (v) => v.toLocaleString(undefined, {
style: 'currency', currency: 'USD' })
const order = JSON.parse(localStorage.getItem('order_data'))
const cancel = () => {
localStorage.removeItem('order_data')
window.location = '/shop/cart/'
@ -18,8 +17,8 @@ const elements = stripe.elements({
fontFamily: 'dejavu, monospace',
},
},
clientSecret: order.stripe_secret,
})
clientSecret: JSON.parse(localStorage.getItem('order_data')).stripe_secret,
})
const paymentElement = elements.create('payment', {
paymentMethodOrder: ['card'],
layout: 'tabs', // or 'accordian'

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -86,14 +86,13 @@ title: Cart
</div>
</div>
<div>
<button style="margin:calc(2vh + 1vw) 0" data-bind="visible:(payment_method()==='USD'), click:checkout,enable:(checkoutEnabled()&&!isLoading()), attr:{title:checkoutButtonHelp()}, text:checkoutButtonText">📃 Create order</button>
<button style="margin:calc(2vh + 1vw) 0" data-bind="visible:(payment_method()==='USD'), click:checkout,enable:(checkoutEnabled()&&!isLoading()), attr:{title:checkoutButtonHelp()}, text:checkoutButtonText">Checkout</button>
</div>
<script>
const API_DOMAIN = '{{env.API_DOMAIN}}'
const ZIPS_TO_STATES = '{{zipsToStates|dump|safe}}'
const ZIPS_TO_ZONES = '{{zipsToZones|dump|safe}}'
const USPS_SHIPPING_RATES = '{{uspsShippingRates|dump|safe}}'
const ZIPS_TO_STATES = JSON.parse('{{zipsToStates|dump|safe}}')
const ZIPS_TO_ZONES = JSON.parse('{{zipsToZones|dump|safe}}')
const USPS_SHIPPING_RATES = JSON.parse('{{uspsShippingRates|dump|safe}}')
</script>
<script src="/assets/scripts/knockout-3.5.1.min.js" integrity="sha512-2AL/VEauKkZqQU9BHgnv48OhXcJPx9vdzxN1JrKDVc4FPU/MEE/BZ6d9l0mP7VmvLsjtYwqiYQpDskK9dG8KBA=="></script>
<script src="/assets/scripts/cart.js" defer></script>

View File

@ -1,10 +1,14 @@
---
layout: layouts/base.njk
title: Checkout
permalink:
dynamic: /shop/checkout/stripe/
---
<h1>📃 Order</h1>
<h1>Checkout</h1>
<script src="https://js.stripe.com/v3/"></script>
<p>page: {{page|dump}}</p>
<p>eleventy: {{eleventy|dump}}</p>
<table style="width:100%;text-align:left"><thead>
<th>Item</th>
<th style="text-align:right">Price</th>

Some files were not shown because too many files have changed in this diff Show More