Learnings, reminders and frustrations written in the moment.
- Question: What's the best way to install Java on a Mac?
- Lakin uses asdf on Windows and it's available on Mac.
- Side quest: Now installing Starship in iTerm2
- I love it!
- Great game for learning vim: VIM Adventures
- Cool podcast on The Science of Learning to Code
-
Prepare raw question/completion data:
openai tools fine_tunes.prepare_data -f <LOCAL_FILE>
- Type
y
to all the prompts - Created
data_prepared.jsonl
- Type
-
Create upload file function
- in
app.js
, export theopenai
object - import
openai
intoupload-file-function.js
import { openai } from "./app.js"; import fs from "fs"; async function upload() { try { const response = await openai.createFile( fs.createReadStream("./data_prepared.jsonl"), "fine-tune" ); console.log("File ID: ", response.data.id); } catch (err) { console.log("err", err); } } upload();
- in
-
Run
upload-file-function.js
:node upload-file-function.js
- File ID created:
file-Jamquc2KjDZZ7AwuUWiGsWgX
- File ID created:
-
Create
fine-tune-function.js
:import { openai } from "./app.js"; async function createFineTune() { try { const response = await openai.createFineTune({ training_file: "file-Jamquc2KjDZZ7AwuUWiGsWgX", model: "davinci", }); console.log("response: ", response); } catch (err) { console.log("error: ", err.response.data.error); } } createFineTune();
- This will take awhile
-
Check on the status of the training by creating a
list-finetunes.js
:import { openai } from "./app.js"; async function listFineTunes() { try { const response = await openai.listFineTunes(); console.log("data: ", response.data.data); } catch (err) { console.log("error: ", err); } } listFineTunes();
- The object contains
status
andfine_tuned_model
properties:... status: 'pending', fine_tuned_model: null ...
- After it completes, it should say something like this:
... status: 'succeeded', fine_tuned_model: 'davinci:ft-personal-2023-07-04-21-35-36' ...
- The object contains
-
Create
test-completion-function.js
which will test (duh) the training model:import { openai } from "./script.js"; async function createCompletion() { try { const response = await openai.createCompletion({ model: "your model ID", prompt: "ask your questions here", max_tokens: 100, }); if (response.data) { console.log("choices: ", response.data.choices); } } catch (err) { console.log("err: ", err); } } createCompletion();
- Paste new model ID for
model
. - Paste an example
prompt
below themodel
.
- Paste new model ID for
-
Once the new model has been tested, refactor
app.js
to use the new interface:- Before:
const res = await openai.createChatCompletion({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: input }], }); console.log(res.data.choices[0].message.content);
- After:
const res = await openai.createCompletion({ model: "davinci:ft-personal-2023-07-04-21-35-36", prompt: input, max_tokens: 200, }); console.log(res.data.choices[0].text);
- Before:
Requirements: Python 3
- Is Python 3 installed:
pip --version
- Properly Installing Python 3
- Note,
pip3
works butpip
did not on Mac. See: Runningpip
gives 'command not found' after successful Python homebrew install
Documentation on Fine-tuning Open AI
- Upgrade Open AI so that you can send it commands:
pip install --upgrade openai openai"[datalib]"
- Build your
data.jsonl
file withprompt
andcompletion
examples.- Pro tip: have ChatGPT build these for you
"Give me 10 commonly asked questions about [javascript, html, css, etc] along with possible completions for each question in jsonl format"
- Descriptive nouns used to build training data:
- javascript
- html
- css
- raster images
- vector images
- git
- Figma
- UX
- responsive design
- visual hierarchy
- the bash terminal
- npm
- semantic html
- css specificity
- css overrides
- css animation
- the document object model
- web typography
- styling SVG
- git merge conflicts
- flexbox
- css grid
- css color
- css selectors
- css variables
- html resource hints
- html entities
- media queries
- html lists
- hero sections
- responsive navigation
- css layouts
- html nesting
- css functions
- browser dev tools
- css frameworks
- component frameworks
- html attributes
- web accessibility
- browser console
- git branches
- When building your data file, use the
.jsonl
extension so that you can use multiple objects in one file.
- Pro tip: have ChatGPT build these for you
- When would you need to train your AI?
- When you want it to respond to your specific topics and not general questions.
Instructions provided by Zack Spring Chief:
- Create an account with OpenAI
- Go to API (vs ChatGPT, DALL*E)
- Follow/read Quickstart Tutorial
- Create API Key: Profile > view API Keys
- Create project, save key in
.env
- Initialize project
- Follow API Reference
npm install openai
- Create
app.js
with example node code:import { Configuration, OpenAIApi } from "openai"; const configuration = new Configuration({ // organization: "org-GtBFKyLXxx4p9EKZOoapne7z", apiKey: process.env.OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); // const response = await openai.listEngines();
- Delete:
organization
(not using it)- last line (
openai.listEngines()
is deprecated)
- Delete:
npm install dotenv
// app.js import { config } from 'dotenv'; config();
- Add
dev
script topackage.json
:"scripts": { "dev": "node app.js" },
- Add
type: "module"
topackage.json
- Do a test run (it shouldn't do anything but run without error)
- Send a test request. Copy and paste this into Postman:
curl https://api.openai.com/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ "model": "gpt-3.5-turbo", "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"}] }'
- replacing
$OPENAI_API_KEY
with new key you just created
- replacing
- Add
readline
functionality to app:import readline from 'readline';
- Add
readline
functionality to end ofapp.js
const userInterface = readline.createInterface({ input: process.stdin, output: process.stdout, }); userInterface.prompt(); userInterface.on("line", async (input) => { const res = await openai.createChatCompletion({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: input }], }); // Log only useful information console.log(res.data.choices[0].message.content); });
- Boot it up and ask it a question (response could take up to a minute or longer)!
- Initialize Git and add a
.gitignore
:node_modules .env
Total time: 45 minutes Test
- Dependencies
- Python 3
Some resources for understanding CSS transitions and animations to a level that I can implement some of Disney's 12 Principles of Animation:
- A great article summarizing Disney's 12 Principles of Animation
- CSS Tricks: Multi-step Animations
- A great Easing Function Cheatsheet
- HTTP 203: Bringing bounce and elastic easing to CSS
- A great deep dive into why you can't add more than two anchors to
cubic-bezier()
- Apparently,
linear()
is a new function that can mimic bouncing in CSS
- A great deep dive into why you can't add more than two anchors to
- CodePen Home The 12 Animation Principles using GSAP and Vanilla Squash example
- Reference: Yaansk
- Reversing an Easing Curve
- Reference: Morwynd
Tutorial Breakdown: Build a Blazing Fast SvelteKit Markdown Blog
- Dependencies:
- Open Props: Supercharged CSS variables
- Lucide: Icon toolkit
@fontsource
Fonts installed withpnpm
:@fontsource/manrope
and@fontsource/jetbrains-mono
- Wes Bos's favicon service
- Synopsis:
- 2:23
- Fonts, Open props, Lucide install
- Site config file uses:
import { dev } from "$app/environment"
- 17:09 - Great intro to [Open Props(https://open-props.style/)] and how it handles modern theming using CSS variables on steroids.
- 2:23
- Stopped @ 17 mins for now
I covered Svelte animations and motion today and learned about deferred transitions!
I didn't really get it at first but I found this article that tries to explain it (it took awhile to figure it out):
This is Part 2, which is now on my reading list, and has a pretty sweet demo:
Skeleton UI: A Tailwind package for SvelteKit
I've been getting acquainted with the Supabase admin panel and the toughest (and most important) bit that I've been trying to process is how auth works. I wish I found these earlier in my journey. They would have saved a lot of trial and error.
Supabase Auth
- Part One: JWTs
- Part Two: Row Level Security
- Part Three: Policies
- Part Four: GoTrue
- Part Five: Google Oauth
- Tips for Clean Code
- Ref: Cordelle
A great example of custom store method arguments, offered by the Great Morwynd:
Working on some ideas for custom right-click menus. An area of SvelteKit I don't quite have a grasp on yet is where browser-based objects can be used.
SvelteKit components can run on both server and browser so how do I work with right-clicks?
First, I found this article outlining the options:
- Browser module
- Meh, seems kind of clunky.
- onMount
- Been there, done that.
- Actions: the use directive
- Looks very promising and sexy, especially since the example is an out-click event.
use:enhance
is one of my learning priorities so I think I'll definitely be exploring this one.
Thinking about nav bars for the new home page. For inspo, some home pages of the nerds I follow and respect:
-
Rich Harris (GitHub; no home page)
-
Mandy Michael (GitHub; no home page)
Happy Robbie Burns Day!
Haggis puts me the mood for authentication. I've had my eye on this tutorial from Huntabyte since SK went 1.0:
Notes
- The two repos install fine but, as expected, the
final-code
version gives me an error:Error: supabaseUrl is required.
- On to the Supabase documentation:
- First question: The tutorial in the docs say to Run "User Management Starter" but I'm not sure if Huntabyte uses this template (I'm not watching the video due to noise).
- I'm going to put this on the shelf for today and run through the video again. Then I'll decide if I want to go with the video or run through this Supabase tutorial. I'll probably do both and compare afterwards.
I've been looking for documentation on the $:
syntax in Svelte. Example:
$: resolveDisabled = rollState !== 'rolling';
$: rollDisabled = rollState === 'resolved';
$: resetDisabled = rollState === 'initial';
$: keepPile = $dice.filter(die => die.keep);
$: rollPile = $dice.filter(die => !die.keep);
- From: king-of-tokyo-sveltekit
The symbols $:
are filtered out when I Google them so what is the domain-specific terminology I should be using? A search for "svelte dollar colon" returns this helpful article:
Nice! It's called "dollar lebel" syntax and it acts as a useEffect()
type of functionality that allows for side effects when some state changes. Pretty slick.
Update: Brian says they're more officialy referred to as reactive statements.
SK Documentation
- Looking to make my endpoints more robust:
sveltekit-blog-starter
on SvelteKit 1.0.whatever
Goal: Create a Sk-based markdown blog that does all the fancy highlighting I need as a teacher of code:
Notes
- Installed the following side-by-side in a
_hello
directory;-
sveltekit-blog-starter
Quick Startnpx degit https://github.com/josh-collinsworth/sveltekit-blog-starter sveltekit-blog-starter cd sveltekit-blog-starter npm install npm run dev -- --open
-
SvelteKit 1.0: Creating a project
-
Created a Skeleton project with No to all the things:
npm create svelte@latest sveltekit-1.0 cd sveltekit-1.0 npm install
-
-
- Re-installing SK with ES Lint and prettier to better match
sveltekit-blog-starter
; - In a new workspace:
- Repeat SK-1.0 install
- Install MD related packages from
sveltekit-blog-starter
- Move src to new install
- Cross fingers
- Notes:
- New packages:
@sveltejs/adapter-static
mdsvex
rehype-autolink-headings
rehype-slug
sass
svelte-preprocess
- New packages:
- I'm now realizing I probably want to process the markdown like they do in
learn.svelte.dev
. - Cloning
learn.svelte.dev
into_hello
$ git clone git@github.com:sveltejs/learn.svelte.dev.git
- don't need to build it; I just want to see how they install the markdown functionality
- Notes:
learn.svelte.dev
usesmarked
instead ofmdsvex
insveltekit-blog-starter
. More research will be needed.- For now, going to try
mdsvex
and getsveltekit-blog-starter
running on sk-1.0 - Installed above packages
- Copied over code from:
svelte.config.js
vite.config.js
README.md
- Ignoring
jsconfig.json
, but not sure if I'll need it later. npm run dev
boots without issue.- Moving over
src
andstatic
- Everything seems to work!
- Observation: PrismJS doesn't recognize the
+++
syntax used inlearn.svelte.dev
to select text inside a code block :(- Looks like they have a custom transformation renderer.
- I don't want to lose
mdsvex
functionality but maybe there are hooks that I can add to process+++
into<span class="hightlight add">
?
- Next steps/questions:
- Should I remove
sass
support in favour of scopedcss
and/ortailwind
? - Convert f22 semester site to SK 1.0.
- Should I remove
Notes: learn.svelte.dev
- Keyed each blocks needs some review later. Having trouble visualizing what's happening with the emojis.
- Await blocks are pretty cool. It broke my brain a bit when
text
is returned to anumber
variable in the template. But then I realized it's just a simple function.
King of Tokyo is going to need some modals. A quick search for "SvelteKit modals" returns two REPL examples:
- Simple Modal: A busy example of multiple types of modals that's a little overwhelming
- A nine-file example that seems to do what I need but it'll take some time to pull out the relevant code.
- Simple Modal Component: A two-file modal example that seems simple but has a lot of extra code to handle nested modals that might not be needed.
Great news for anyone using Josh Collinsworth's sveltekit-blog-starter (i.e. me). He's recently updated his code to (hopefully) prevent erroring out with build .503
and higher.
Maybe the time is right to fork the theme for my own blogs?
I've got to learn some Strapi for teaching and also for a potential backend for some projects on my never-ending list of content projects (although this list actually ends):
- Resource library for great videos and articles to use as homework;
- Central lab repository for teachers;
- Definitions library for domain-specific terms
Since Nuxt3 (teaching requirement) is the new hotness, I found this video series by Pixelhop:
Building a JAMstack shop with Strapi 4, Nuxt 3, Snipcart
- Part 1: Project Setup
- Part 2: Site structure, layout and core components
- Part 3: Product entry with Strapi
- Part 4: Snip cart setup
User Story: As a game host, I'd like to quickly update my players' stats, so that they can stay updated on the state of the game.
Requirements:
- A counter component
- default value: 0
- UI for increment and decrement
- State is a $tore?
Work-in-progress Counter
Attributions
Happy Thanksgiving!
I finally figured out why some repos don't show up in the drop-down when I try to convert a Projects (Beta) draft issue: Issues isn't turned on!
I started the fork of Josh's sveltekit-blog-starter
today during the stream and, of course, I ran into issues upgrading from SK .472 to .503.
- Error: Some prerendered routes were not prerendered;
After some searching on Google and in the changelog, it turns out that this has been happening for awhile but, as of .503, SK "throws an error if prerenderable routes are not prerendered (#6974)".
The bug hunt made me realize a few things:
- I don't really understand how prerendering works in SK:
- What makes a route prerenderable?
"The basic rule is this: for content to be prerenderable, any two users hitting it directly must get the same content from the server. Note that you can still prerender content that is loaded based on the page's parameters as long as all users will be seeing the same prerendered content."
- Can SK prerender dynamic routes?
- Yes, it looks like it.
crawl
(true
by default) will find all the local generated links as it goes through the site.
- Yes, it looks like it.
- Is there a way to dynamically create the
entries
config to handle things like pagination and tags/categories?- No, but there's a
*
wildcard for routes that aren't dynamic.
- No, but there's a
- Can pure
+server.js
routes be prerendered?- Yup! (in theory).
- Why does Josh's template use pure
+server.js
routes to retrieve posts and pagination?- Can't find this in the docs, but it points to my current lack of knowledge of what
+page.server.js
does and how it's different than+server.js
.- I think I get the general idea (the former can run on the frontend) but why can't these queries be done in a statically generated manner. Or does it?
- Can't find this in the docs, but it points to my current lack of knowledge of what
- What makes a route prerenderable?
Some key documentation that helped me answer the questions above:
Is Figma Dead?
- Breaking news (from a couple days ago): Adobe acquires Figma for $20B
- Is Figma Dead? - Penpot, the Open Source Figma Alternative
CSS Things
Exciting news from last week: SvelteKit is now in Release Candidate!!!
- Current: .468 (what's the worst that could happen?)
- Update: nothing
Posting this segment of a stream by Rich Harris about how to properly post a reproduction repo (repro) when submitting an issue:
This will come in handy if I have to submit a bug with how SvelteKit (and Vite?) handle markdown content when using page endpoints.
New videos:
- New features in Chrome Dev Tools
- Chapters:
- 0:00 - Intro
- 0:13 - Step-by-step replay in the Recorder
- 1:06 - Support mouse over event in the Recorder
- 2:21 - Identify FOIT/FOUT in the Performance insights panel
- 3:02 - LCP in the Performance insights panel
- 3:40 - Top layer badge in the Elements panel
- 4:38 - Attach wasm debugging info during runtime
- 5:06 - Protocol handlers in the Manifest Pane
- 6:38 - Bonus Tip: Use Recorder to record DevTools user flows
- Google Recorder, where have you been all my life?
- Chapters:
- How to speed up your workflow with Console shortcuts
Josh Collinsworth fixed an issue I submitted! I wish I had submitted a Pull Request but I wasn't sure how to solve the issue with scss
. It turns out his fix was to
I've changed
:where
to:is
, which allows the heading styles to override the generic styles.
- The project is currently on
.403
- The project is based on a fresh init of sveltekit-blog-starter
Which is easier?
- Clone a fresh project re-add all the changes done since the project began?
- Manually make the changes committed over the last 8 months?
Given my custom URL handling with blog posts, it's probably easier to got with #2. It'll get me acquainted with the theme if I use it for future SK-markdown projects.
To get the project up-to-date, I need to:
- Update SK to
.431
or higher.- a lot of the fixes will be in Josh's commit below.
- Apply fixes that Josh made to sveltekit-blog-starter since I copied the files in Jan 25, 2022.
- Using the git log of
sveltekit-blog-starter
as a cheat sheet. - First obstacle: my build version should be
.405
or higher before I can use the fancy route migration script the SK team created. - Apparently Jess was recently successful at locking SK to a particular version so I'll wait until she's around to figure this out?
Bryce referred me to the colonist.io website as an example of an open game platform for Settlers of Catan.
- it looks like it's free but not open-source as far as I can tell. I don't mind that.
- I'm mostly interested in the interface for rolling and cards as it relates to KoT.
- Update: I played it a bit and the interface is a little irritating as a first time user.
- Some of the elements are small. For example, I couldn't make out some of the ports on my 11" MacAir. I'm probably an edge case but the
canvas
element isn't responsive. - There aren't any tooltips when you hover over an interface element. This would have been handy with the small ports.
- It's not obvious who's turn it is and what I need to do. I eventually found the "log" but there was very little visual hierarchy pointing me in the right direction.
- I think with a bid of play time, these issues would fade, except for the unreadable ports.
- Overall it's an impressive project build on
canvas
. How would someone build this with the DOM?
- Some of the elements are small. For example, I couldn't make out some of the ports on my 11" MacAir. I'm probably an edge case but the
- Tooltips! Anything the player hovers should give some insight into what it is, what it means and when it's important.
- Don't waste space. Catan has a lot going on but even the above implementation is wasting screen real estate with the ocean.
- Make the important bits big a loud. Make it clear what the player needs to do or doesn't need to do by adding visual hierarchy to the game elements.
With the dice roller being pretty functional, the next feature will be the deck shuffler. With those two components, it should be possible for a group to play a game of King of Tokyo over Zoom if they keep track of their own VPs, Health and Energy.
Deck requirements:
- Set up: shuffle deck
- Deal 3 cards face up (name for this space?)
- Buy a card (Discard cards only)
- Replace a bought card from the top of the deck
- Discarded card -> discard pile
Some sketches for a new dice roller interface:
The changes:
- both keep and roll piles on one row
- keep pile has inset border to simulate a groove
- auto resolve on 3rd roll?
Word on the street is that many breaking changes are coming down the pipe so I felt it prudent to update my SK projects to the current version before storm comes. My worry is packages like mdsvex
may break and need updating.
Some problems I ran into while updating browsertherapy-v2:
- The following fixes were found in sveltekit-blog-starter:
- Vite config has been moved to a new
vite.config.js
file. package.json
scripts now usevite
instead ofsvelte-kit
:"scripts": { "dev": "vite dev", "build": "vite build", "preview": "vite preview", }
%svelte.head%
and%svelte.body%
are now%sveltekit.head%
and%sveltekit.body%
, respectively.
- Vite config has been moved to a new
- Additionally, I had to make the following fixes:
-
Vite 3 is now required.
-
HTTP method functions need to be uppercase:
export const get = async ({ url }) => { // some code }
becomes:
export const GET = async ({ url }) => { // some code }
-
It got a little scary but it turned out alright.
Cool sites/tools mentioned in Coding Garden (ref by Danielle!):
- JavaScript Algorithms and Data Structures
- cloak VS Code extension for hiding secret .env keys on stream.
- TODO Tree VS Code extension
DNS Update: Finally figured it out. There's a separate AWS admin panel to change name servers if they're registered with AWS. I posted the details here.
I hadn't realized that Netlify was choking on my BT builds since I added my fancy hidden date naming system to my blog filenames.
I was seeing this error when I was booting up the site:
- It references this page of limitations of using variables for dynamic imports, that I learned about back in June.
- I just had to refactor my file paths so that the variable portion didn't include the relative path and extension.
DNS Update: slav-arcadechain
gave me some pointers on how he got his setup to work by abandoning Netlify and serving the DNS using AWS. Will try to get that working tomorrow.
Heydon Pickering Very high quality browser vids published monthly(ish). Current faves from researching SVGs (search: "svg commands"):
- Making Future Interfaces: Inline SVG
- How do I draw a line?
- Making Future Interfaces: Unusual Shapes
- Making Future Interfaces: ES Modules
- Not SVG related but a great intro to browser support.
Also found this intro to SVG elements:
- Learn SVG through 24 examples by Hunor Márton Borbély
And this great SVG vid on Google Chrom Developers
DNS Update: slav-arcadechain
gave up on support and decided to use AWS name servers instead. I'll do the same if someone doesn't reply by tomorrow.
What are the odds that my name servers updated before Netlify's?
Turns out, I don't know yet? The domain is still down and, although it hasn't been 24 hours, I'm preparing for the worst.
Here's what I know so far:
The ns
records are correct but not propagated:
$ dig browsertherapy.com ns
;; ANSWER SECTION:
browsertherapy.com. 86400 IN NS dns1.p05.nsone.net.
browsertherapy.com. 86400 IN NS dns2.p05.nsone.net.
browsertherapy.com. 86400 IN NS dns3.p05.nsone.net.
browsertherapy.com. 86400 IN NS dns4.p05.nsone.net.
$ whois browsertherapy.com | grep -i "name server"
Name Server: NS-1273.AWSDNS-31.ORG
Name Server: NS-1537.AWSDNS-00.CO.UK
Name Server: NS-499.AWSDNS-62.COM
Name Server: NS-828.AWSDNS-39.NET
$ dig browsertherapy.com NS +trace
; <<>> DiG 9.10.6 <<>> browsertherapy.com NS +trace
;; global options: +cmd
;; Received 17 bytes from 10.0.0.243#53(10.0.0.243) in 101 ms
This could still be a propagation issue (i.e. I don't need to do anything) but I'm skeptical. I'm not sure what it means when the returning name server is from the private network I'm on? From the docs, this should be Netlify.
The point that worries me is the SOA is still pointing to AWS.
$ dig -t SOA browsertherapy.com
;; ANSWER SECTION:
browsertherapy.com. 900 IN SOA ns-1273.awsdns-31.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
It feels like this is something that AWS will manage automatically? There's also the chance that the .com registry doesn't like the absence of IP addresses with my name servers but, since the Console didn't throw an error, I don't think that's the issue. If any TLD wouldn't care, it'd be .com.
Still in purgatory.
Update: Found this support article posted around midnight:
- AWS Route 53 to Netlify domain migration
- They mention updating their SOA, so I changed mine to match:
dns1.p05.nsone.net. hostmaster.nsone.net. 1 blah blah blah blah
- They mention updating their SOA, so I changed mine to match:
Update2: It worked almost immediately! (The odds were pretty low, it turned out.)
curl -s -v http://www.browsertherapy.com 2>&1 | grep -i server
< Server: Netlify
- The website is loading under
http
but Netlify's HTTPS Verification thinger sees the internal dns as inactive. This is the same problemslav-arcadechain
mentions in their thread. - Going to try changing the SOA to point to p01? It'll probably break everything but maybe I'll strike gold.
- Nope, broke it. Back to
.p05
.
- Nope, broke it. Back to
- TODO: Reply to
slav-arcadechain
's thread to confirm I'm having the same problem. Plus props for catching me up!
I'm beginning to migrate three of the posts from the legacy Browser Therapy website and it'll take some work to get the markdown to play nice with SvelteKit.
One feature that's broken is the final embedded Codepen. Luckily, I happened upon this post of components for embedding various things:
- SvelteKit Embed by Scott Spence
I had the domain pointing at GitHub when it was a Jekyll website. I haven't been able to deploy SvelteKit to GH Pages yet. Yet! Whatever, Netlify seems to love SvelteKit and the repo sync is buttery smooth.
Custom domains may be another matter. I'm in propagation purgatory waiting for my name servers to update.
Search: "zsh dns tools"
-
reminded about
nsloop
but I remember there's another one:- Suggestion: "nslookup vs..." -> dig
- Top result is a misleading answer unless you pay attention to the dates:
- Suggestion: "nslookup vs..." -> dig
-
Basically,
dig
uses the OS andnslookup
uses it's own things, and was considered deprecated but now it's not. -
From slm:
So it would seem that
nslookup
is perfectly fine to use along withdig
. In addition to the 2 tools using different resolvers, there are things that are easier to do indig
vs.nslookup
, thoughnslookup
is generally the easier of the 2 tools to use day to day.Also
dig
's output is typically easier to parse in scripts or in command line usage. -
Going to start with
dig
to potentially troubleshoot my dns tomorrow.
Search: "dig ns records"
- Attribution: Edward S.
- A little
dig browsertherapy.com
shows myns
records deleted but the new ones aren't there yet. Troubling? - Nope! A little
dig browsertherapy.com ns
shows my records. - Searching the Netlify docs:
- Delegate your domain to Netlify
- Leads to DNS & HTTPS troubleshooting tips for tomorrow.
- Delegate your domain to Netlify
- What are the odds that my name servers updated before Netlify's?
Bubbles sent me this banger of a presentation on Async stores in SvelteKit:
With the BT launch coming close, thoughts are beginning to turn to board game mechanics to help fill out the programming with game theory. This video on the "I cut, you choose" mechanic references a great directory of board game mechanics, along with references to the games that use them:
- Board Game Mechanics
- Dice related mechanics in the list:
Research: Card designs for blog and article posts.
- Card UI Examples and Best Practices for Product Owners
- Designing cards
- Material UI: Cards
- Excellent summary of basic card pattern best practices.
Example card diagram from the Material Design docs.
Yet another example card diagram from the Material Design docs.
CSS Tricks card example with generic image.
I've been knocking down some BT cards this afternoon and now have to do a tricky one: adding a Twitch link to the main nav.
- Problem: the SK theme I'm using only supports one type of nav link. Baiscally, I need to either add of fake a new Utility nav bar.
- Solution: figure out how to add an additional class to each link so I can style the Twitch item with the logo and matching coloured background.
- The theme already supports
active
links usingclass
. Otherwiseclass
is empty. Now I just need to figure out how this Svelte syntax works:<a href={href} on:click={maybeCloseMenu} class:active={isCurrentPage} aria-current={isCurrentPage ? 'page' : false} >
- Specifically, how do I add classes to
class:active={isCurrentPage}
?
- Specifically, how do I add classes to
- Svelte's terminology for this is "class directive"
- Aaaand Svelte wins again. I can just add a separate class directive and Svelte will chain them automatically:
<a href={href} on:click={maybeCloseMenu} class={page} class:active={isCurrentPage} aria-current={isCurrentPage ? 'page' : false} >
- I had to make some other changes to gain access to the
page
value but it was pretty straight forward.
- I had to make some other changes to gain access to the
- The theme already supports
I finally committed to streaming every Saturday at noon by setting up a repeating event in my Twitch Schedule! I don't want to do the Dice topics on short notice for this weekend so I'm going to try building a cross-fade slider thingy that compares JWST and Hubble images:
- Example WebbCompare app by John Christensen
- Source code
- Originally referenced by Joe Scott
- Related Reddit thread
- TODO: Find new images from recently released (today, supposedly) images used for commissioning the telescope.
Currently trying to get the marketing side of BT online. I've still got the BT MailChimp account from the original sessions I did a few years ago. Copy and pasting the embed code from the admin panel doesn't work with SvelteKit, though.
I found this article with sample code that might be useful:
- Article: Build your own SvelteKit Boilerplate: Using Mailchimp with Endpoints with YouTube video
- Repo: csellis/svelte-backpack
- Ugh, the docs and interface of MailChimp is a pain. Currently evaluating SendinBlue as an alternative. So far so good...
- TODO: Setup a reCAPTCHA account for the hosted sign-up form.
- TODO: Breakdown Board Game Design and the Psychology of Loss Aversion
- Lots of theory and examples of how to use loss aversion to make your games better.
- A book referenced in the talk: Thinking, Fast and Slow by Dan Kahneman
Session goal: Feature: Dark mode cont'd
Getting back to the Dark Mode toggle, I'm unsure if a store is needed? It feels like this can be done with CSS Variables and a data attribute. Normally I'd take the time to figure it out myself but I think I'll cheat and take a look at Josh's implementation on his live blog. It doesn't respect the system preference but I'll figure that out later.
- He's using stores and setting the mode with classes. I'll eventually use data attributes, I think? I'm not sure why but it just seems cleaner.
- That said, I'm putting the Dark Mode toggle on the shelf for now; re-designing the default theme will be enough work without needing to think about another theme. BUT, I look forward to setting new colours for the logo when it comes to it.
Session Goal: Refactor banner
- Time to finally do some "design"! I did a mood board back in April that I can now use to properly rip off other designers.
- That said, I'm going to go with the traditional left/right logo/nav layout for the banner. It works and this isn't a portfolio site.
Been thinking about why Browser Therapy exists. Not only why someone would want to watch a stream but what it means to me and why I'm doing this in the first place.
- Code craft: Proceed with the indent of mastering your craft. Seek challenges and find progressively more difficult problems with code.
- Accountability: Commit to the journey, set some goals and share your progress with others.
- Escape: Code isn't just about work. It can also be a tool of self-expression but the journey doesn't have to be fun.
These are not prescriptive but are core principles to direct me when I get distracted.
Session goal: Feature: Dark mode
Plan:
- Try implementing the Ultimate Dark mode toggle exercise in SvelteKit.
- Compare the implementation with the one Josh uses on his personal blog
- Note: This implementation doesn't respect system dark mode preference.
Brute force notes:
- First of all, coming back to this after a year tells me I need to write a step-by-step of my final solution:
- Add HTML for toggle:
<!--Will add toggle switch here--> <div class="theme-switch-wrapper"> <label class="theme-switch" for="checkbox"> <input type="checkbox" id="checkbox" /> <div class="slider round"></div> </label> <em>Enable Dark Mode!</em> </div>
- Add the CSS:
.theme-switch-wrapper { display: flex; align-items: center; } .theme-switch-wrapper em { margin-left: 10px; font-size: 1rem; } .theme-switch { display: inline-block; height: 34px; position: relative; width: 60px; } .theme-switch input { display:none; } .slider { background-color: #ccc; bottom: 0; cursor: pointer; left: 0; position: absolute; right: 0; top: 0; transition: .4s; } .slider:before { background-color: #fff; bottom: 4px; content: ""; height: 26px; left: 4px; position: absolute; transition: .4s; width: 26px; } input:checked + .slider { background-color: #66bb6a; } input:checked + .slider:before { transform: translateX(26px); } .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; }
- Add the JS. This might take some refactoring. Josh used stores for some things and it feels like it's a good way of handling state.
- Luckily, there's a decent tutorial on stores in the Svelte docs.
- Add HTML for toggle:
Next TODOs for BT blog:
h2
-h6
is showing body text font -> accent font- posted an issue for Josh's theme
.site-title
is using accent font -> code font?- Refactor Ultimate Dark Mode Toggle for this theme.
Updated bt-v2 Project board. I had to delete most of the existing cards that were attached to the previous version of the site (before I adopted the theme).
- Interestingly, there doesn't seem to be a way to directly link to individual cards/items in the project?
Goals: Copy/pasted from GH Project:
- Add markdown test page
- Install remark-containers
- Install remark-attr
- Install remark-deflist
Brute force notes
- Made a gist for extended syntax test page.
remark-attr
syntax causes a compile error in mdsvex.
- Process for installing
remark
plugins undermdsvex
- Confirm the npm package names:
- Install packages:
npm i -D remark-attr remark-containers remark-deflist
- Import packages:
// svelte.config.js import attr from "remark-attr" import containers from "remark-containers" import defList from "remark-deflist"
- Add to
svelte.config.js
// svelte.config.js remarkPlugins: [ defList, containers, attr ],
- Bonus: close the issues from the command line to watch the Project cards magically move from In Progress to Done!
git commit -m "Closes #1, closes #3, closes #4, closes #5"
Research: for potential stream topics
- Flip animations | HTTP 203
- Bezier Curves by the Coding Train
- Add noise suppression (full notes)
- Click cog next to the sound source -> Filters
- Click
+
to add filter - Select
Noise Suppression
-> Custom name -> OK - Tweak Level. Try -20dB?
- Add Featured Chat
- Try adding a countdown timer?
- Try installing Stream Countdown Timer Stream Deck plugin even though it doesn't list Mac in the requirements.
- Project workspace setup
- Clone some repos!
- Hello world
- BT Websites
- Journals
- Maybe some others
- Clone some repos!
Attribution: Josh Collinsworth's excellent sveltekit-blog-starter theme.
My steps for customizing the theme in case I have to do it again (like for my personal blog):
- Update
/lib/config.js
; - Replace fonts:
-
Font values are stored as CSS Variables in SCSS:
/* /lib/assets/scss/_vars.scss */ --accentFont: 'Libre Franklin', Georgia, Times, serif; --primaryFont: 'Libre Franklin', sans-serif; --codeFont: 'Fira Code', monospace;
-
And the fonts, themselves, are imported directly in
/src/app.html
<link href="https://fonts.googleapis.com/css2?family=Libre+Franklin:ital,wght@0,400;0,800;1,400;1,800&display=swap" rel="stylesheet">
I would rather use Amaranth for the Heading font and Open Sans for body text. I'll need to do some leg work to figure out which styles and weights I need for the default styles to work properly. In this case it looks like I'll need
400
and800
weights for both regular and italic?It's also the same for both accent and body fonts.
-
TODO: Figure out what the performance hit is for downloading normal and bold weights for two different accent and body text fonts. Does SvelteKit have a magic way of loading them performantly? Is it too soon to bother with Variable Fonts?
-
Draft font set:
- Accent
- Amaranth
- Regular 400
- Amaranth
- Body text
- Open Sans
- Light 400 with Italic
- SemiBold 700 with Italic
- Open Sans
- code
- Fira Code
- Regular 400
- Fira Code
- HTML import
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Amaranth&family=Fira+Code&family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
- Accent
-
Are italic font sets needed? What's their impact on performance?
-
TODO
h2
-h6
is showing body text font -> accent font.site-title
is using accent font -> code font?
-
- Update colours
- hex colours but nicely defined:
:root { // Colors --accent: #E63946; --background: #FAF9F8; --lightAccent: #A8DAE5; --lighterAccent: #E6E8E4; --dark: #457B9D; --darker: #1D3557; --slate: #2F3948; --white: #fff; --black: #152030; --ink: var(--slate); --paper: var(--background); }
- Some options for a new colour theme:
- convert
hex
intohsl
- use a pallet from a movie/image/art screencap?
- convert
- Dark mode
- I love the use of
--ink
and--paper
CSS variables. - TODO: Refactor Ultimate Dark Mode Toggle for this theme.
- I love the use of
- hex colours but nicely defined:
- Update Prism theme?
$lib/assets/scss/_prism.scss
- How can this be changed? To what?
- Audio is still present in OBS if the gain on the Scarlett is turned completely down. Probably due to the boosted gain setting.
- Highlights
- @20:50 - Noise Suppression filter (RNNoise)
- @29:33 - Successful featured chat!
I spent a good part of the afternoon adding a dynamic route for single posts stored behind a hidden directory. Also, a post with a file name of /2022-06-23-how-to-function
would have a URL endpoint of /how-to-function
. That way I can order my content by date and not have the date pollute my URLs.
But, that's just one victory in my journey toward a fully functioning blog for BT and there's still a long way to go. That's why I'm going to, instead, start over using Josh Collinsworth's sveltekit-blog-starter as a starting point.
It seems to have a lot of the fine points taken care of (like 404s and 500s) and it's minimal enough to build upon. First up: add the date stuff in the first paragraph above...
Oh day of days! Josh Collinsworth replied to my email about his article! He pointed me to two of his repos that apparently do the things:
- His blog
- SvelteKit starter that he uses for his blog
And it looks like this mysterious import()
function is what I've been looking for. It's deceptively hard to find documentation on this function. Josh's (we're on a first-name basis, whatevs) article uses import.meta.glob()
, which is great for pulling front matter from markdown, but I'd love to find an article/doc/whatevs giving me the low-down on this, like:
- Is it a Vite object? It feels like it.
- How does it interact with SvelteKit?
- Is it the reason my code doesn't work with Page Endpoints?
- Is it compatible with SSG?
- What's the most performant way to full a full directory of markdown files?
- Does it work asynchronously?
Session goal: load markdown files from a hidden directory
The more I dig into this whole hidden directory requirement for the BT blog, I wonder why they need to be hidden in the first place. It would be much simpler to just dump all these posts in a blog
directory and be done with it.
But then I remember that I want to name my files with the date prepended to the title and then have the slug just be the "title" without the the date. It also be nice to be able to add an optional slug to the front matter of a post to override the whole system.
All great ideas (maybe?) but the rabbit hole is beckoning. Back to Brute Force guidelines: get the basics working first and worry about the fancy shit later.
Brute force
- I've been searching for ways to import individual posts and the same blog article I've been using keeps coming up. I even sent him a message from his website contact form asking if I'm on the right track.
- Current theory: the best way to handle this is to setup an additional
/posts/[slug].json
endpoint and handle it with anotherload()
just like the list entry endpoint. From there I can add any logic I need once I get a base[slug]
endpoint working. - Ugh, I just realized that
import.meta.glob()
only imports the front matter of md files. It seems obvious now that I think about it. - After some research it looks like the answer may lie in the
mdsvex
component. Based on this issue, it looks likepngwn
is pretty responsive and the poster of this issue had his documentation PR accepted! - After much research and failed attempts, it's very difficult to dynamically import a markdown file as a component due to limitations with the bundler. It makes sense now that I think about it: the bundler doesn't know the path at compile time because it's a "runtime" kind of situation.
- Moving back to endpoints. First obstacle: is there a way to import the whole file and not just the meta data? Worst case, I guess I could try a basic readfile-type function.
- I found two very intriguing videos on markdown blogs in sveltekit:
- SvelteKit with MDsveX and Auto-Import of Svelte Components
- Source code
- The code is pretty busy but mature!
- TODO: teardown
- Building a blog with SvelteKit, TailwindCSS, and MDsveX by Jeffrey Pohlmeyer
- Companion article
- Source code
- Part 2: Adding Styling, Searching, Custom Components
- TODO: walk-through
- SvelteKit with MDsveX and Auto-Import of Svelte Components
Research for the next couple meta Twitch sessions to figure out:
- Blog
- how to load markdown files in a hidden directory
- How to use [slug] (dynamic routes) in Svelte and SvelteKit by David W Parker
- This one is from April 2021 so might be a bit out of date...
- How to use [slug] (dynamic routes) in Svelte and SvelteKit by David W Parker
- how to load markdown files in a hidden directory
- OBS/Twitch
- Adding a sound gate to OBS to cut out the hvac from the lav mic
- OBS Studio - Advanced Mic Settings (Noise Removal, Compressor, Noise Gate) by Gaming Careers
- Good summary of sound filters. I'll probably just need a Noise Suppressor? The others seem more for gaming.
- Would a gain filter be better than what I did last stream by using
Edit > Advanced Audio Settings
for boosting volume?
- OBS Studio - Advanced Mic Settings (Noise Removal, Compressor, Noise Gate) by Gaming Careers
- How to display individual Twitch comments on screen in OBS
- How To Show Chat Messages On Stream by Gaming Careers
- Sponsor: Epidemic Sound - royalty-free music for streams
- Covers "Featured Chat" that should be able to handle everything I need! It uses a third-party platform that I can include in OBS using a web source.
- How To Show Chat Messages On Stream by Gaming Careers
- Adding a sound gate to OBS to cut out the hvac from the lav mic
I think I already found the answers to my questions but Gaming Careers has a lot of other great videos:
- 7 Free Tools to IMPROVE Your Twitch Stream
- VDOninja: I think this is what other streamers use to show video/audio of guests?
- Media Looper
- Crossclip
- Twitch Creator Goals
- Triggerfyre
- Free Webcam Masks
- NOOBS CMDR
- Upgrade Your Stream Deck: 9 Advanced Tips For Streamers
- It details lots of cool tips but I have a feeling they only work on PC :(
- But there's:
- Countdown Timers and Counters
- Webcam Settings Restore: for when OBS forgets my cam settings
- There are more that look awesome but I don't think I need them (yet).
- How To Make a CUSTOM Stinger Transition WITH Track Matte
- This is pretty involved and uses Adobe After Effects. BUT, I admit this would be cool to implement. Basically, OBS bow natively supports a "track matte" that let's you do all the things when transitioning between scenes.
Software install list for M1 Mac Mini initial setup:
- iTerm -> Oh My Zsh!
ZSH_THEME="gozilla"
- homebrew
- Git (double-click installer)
- nvm
- VS Code
- Live Server
- Code Spell Checker
- GistPad
- Zoom
- Discord
- Rectangle
Session goals:
- TODOs from yesterday: Remove extraneous category endpoints.
- Clean up nav so they don't link to the old category links.
- Maybe remove the whole nav and replace with Home and About (stream schedule, rehash of the Twitch description)?
- Add post item pages for the blog.
- Write out a session plan for the stream tomorrow.
Brute force:
- Nav and post category cleanup has been pretty straight forward but the post item links are still broken.
- Going to try building a dynamic endpoint for
/blog/slug
, which will pull content from the hidden/_posts
directory.- How should slugs work?
- Auto-generate from the title?
- Include the date?
- Will the format change based on category?
- How should slugs work?
The streaming rig is physically set up and I'm ready to start testing some Twitch streams. Anything I do live should have a session plan that viewers can reference so I guess it's time to get back to the Browser Therapy blog/website.
Goal: Implement list entry and item pages for Articles, Guides and Challenges so I can write out a plan for the first Twitch test (which will probably be setting up initial software).
Plan:
- Follow my fave SvelteKit blog tutorial
- Question:
- Should all posts be in the same folder with
category
properties in the front matter? - How to title posts? Date with title? Should dates be used at all in the title?
- Should all posts be in the same folder with
Brute force:
- It's been awhile since I've worked on this repo. Almost scared to update the SK version. It's currently at
next.345
. - There are a couple breaking changes between
next.345
andnext.350
but I don't think I need to worry about them. - I'm tempted to only update SK but it's probably best to do a full
npm update
?added 98 packages, removed 2 packages, changed 36 packages, and audited 246 packages in 2m
- And everything still works. What a whole lotta nothing.
- list entry pages are added.
Walkthrough:
- The list entry pages seem a little clunky. I ended up just copy/pasting the code across the three directories for guides, challenges and articles.
- My gut tells me that it's a better idea to put all the posts in one directory and create hard-coded routes for the three categories of posts.
Optimization:
- Following the instructions for dynamic categories but without the dynamic bits.
- Ended up grouping all the posts into a single directory. I had to add some filter logic to the new endpoint but it all seems to be working. Problem: I had to put all the posts into a hidden
_posts
directory so I'll need to figure out how and where I want the posts to exist by adding a dynamic route. - TODO: Create a dynamic route(s) for individual posts.
- Assumption: it's better to route all posts through a single endpoint will be better for seo?
or, to make route logic simpler by dedicating a segment for them:
tld/[slug]
tld/posts/[slug]
- Assumption: it's better to route all posts through a single endpoint will be better for seo?
- TODO:
Remove extraneous category endpoints. There's not enough content to require categories. - Todo: Dedicate to a migration schedule - wbdv content -> posts
- what content should be dated as posts?
- what content is better as static content?
- what's the learning goal(s)?
Bubbles sent me this sveltekit component for flow diagrams:
Story: As a game designer, I want to post a state diagram in the browser so that I can share/record game ideas.
- See: Github Project
Session Goal:
- Install hello-svelvet
Plan:
- Use Create SvelteKit skeleton app gist to boot up a quick project.
- Use the Svelvet Docs to install
- Add a component that describes the latest draft of the King of Tokyo state diagram:
Brute force
- Made this Gist because I've been making a lot of SveltKit apps from scratch lately.
- Copied demo code from Svelvet Basic Usage page.
- and it just works!
- Buuuuut, the functionality is pretty limited:
- The entire diagram needs to be manually positioned? Although you can drag nodes and re-position, there's no way to save the new positions.
- Looks like edge anchor locations are hard coded for the top and bottom. That's pretty limiting.
- I got a rudimentary state diagram working but it took a lot more work than it needed to. Ended up having to inspect all the nodes each time I moved them so I could copy the new coords to the static definition.
- Conclusion: It's a neat proof of concept but I'd need a really good reason to build diagrams in SvelteKit. Even the most basic general diagram tool will beat this.
Deploying SK to GH Pages Deploying this code isn't needed but my last attempt at deploying SvelteKit to GitHub Pages failed miserably so I'll give it another shot and send my diagram to Bubbles.
- This article didn't work using a
gh-pages
branch. - New article: How to Deploy SvelteKit Apps to Github Pages using the
/docs
directory.- And I get a 404 error. That's disappointing :(
Having a coding session at PinBar with Ash. I'd love, love, love to keep working on the dice tower but I've had the markdown blog project sitting on the shelf for too long. It'll probably take a half-hour just to get back up to speed on where I left off?
Update: chased a routing error
- TODO: repost as a new discussion.
I wanted to work on some design aspects but I forgot I fell asleep coding a couple days ago. It took awhile to remember what I was in the middle of, but I managed to figure it out and clean up the code to a working state.
It's now overtime for Game 5 against the Oilers. Not sure how much work I'll get done tonight... and they lost.
BUT! The refactor made support for multiple RPG-style dice notation relatively easy.
Eureka! I think I figured out a way to clean up the dice tower API. D&D has a notation for rolling dice:
2d6
: two 6-sided diced8
: one 8-sided die- etc
So, I can use data types for recognizing what to roll and how many:
- integer: shorthand for one numeric die
6
: 6-sided die5
: invalid die (according to my rules)
- string in
xdy
format: rollx
number ofy
-sided dice2d10
: roll two 10-sided die
- string in
dy
format: oney
-sided die- d20: one 10-sided die
- array of strings (not in
xdy
format): one custom die- could also be an array of objects if there's an advantage to including more info on the custom faces.
Session goal: refactor last night's code to use strings in xdy
format.
- keep it simple:
arg
is just one string. Leave multiple sets of dice for later. - keep current integer shortcut for simple die
Plan
- use regex to split string,
return null
if pattern does not match. - is it worth literally building arrays for each die or just return the random integer? nah.
Brute force
- regex is a blast from the past. After a refresh, it doesn't look like there are many differences from my Perl days.
\d
for digits^
and$
for the start and end of the string*
for zero or more matches
- to keep things simple I'll match all potential sides of dice and filter out non-isohedrals later.
- matching on
/^(\d*)d(\d+)$/
seems to work!2d10
->[ "2d10", "2", "10" ]
d6
->[ "d6", "", "6" ]
- matching on
- Aaaand done!
Usage
- Pass an isohedral integer
x
todrop()
anx
-sided die.6
-> random[1-6]
5
->null
(not a valid die; not isohedral)
- Pass an
Array
of isohedral integersn
to roll and sum eachn
-sided die[4,6,10]
-> random[3-20]
[4,5,10]
-> random[2-14]
because5
is not valid
- Pass a string that matches rpg die notation to roll a set of like-sided dice. RegExp ->
/^(\d*)d(\d+)$/
2d6
-> random[2-12]
d4
-> random[1-4]
2dTwenty
->null
Walk-through
- TODO: Add support for an array of rpg strings!
TODO: Print sum to the pageTODO: Add form for adding a text field forarg
- TODO: Add support for verbose results and
return
an object instead of an integer. TODO: Move duplicate code to aisIsohedral()
function.!allowedFaces.includes(parseInt(notationMatch[2]))
TODO: Move duplicate code to arandDieFace(faces)
whenfaces
is an integer.Math.floor(Math.random() * faces) + 1
- Question: better to use
Math.ceil()
instead of adding1
?
Optimization
randomDieFace(faces)
andisIsohedral()
are probably a good place to clean things up.- And done.
Reflection I'm now at point in the project where I could go in a couple directions: wide or deep.
- Add support for multiple sets of rpg notation, OR
- Add support for verbose results, OR
- Add a form for input and print results to the page.
It think #3 increases the value of #1 and #2.
Goals:
- TODO: Add form for adding a text field for
arg
- TODO: Print sum to the page
Brute force
- When it rains regex, it pours! I thought turning a comma and/or space delimited text field would be hard to dynamically turn into an array but
String.split(/[, ]+/)
did the trick.
First step toward Calgary Coup: the dice roller. I did some research into the svelte-fsm
package and it looks great for the larger application. The dice roller, however, doesn't need states. In fact, it should probably just be a pure function.
- The two "axis" of logic (there's a better term for that?) are:
- is there just one die or multiple dice?
- is each die basic (faces are sequential numbers starting at 1) or custom (faces can be anything)
I've created a dice tower function that supports single and multiple numeric dice. It wasn't too bad but a lot of energy had to be spent properly scoping the session. Limiting the scope to numeric dice was the key in avoiding rabbit holes.
Given:
roll(arg);
So far the roll()
will:
return null
whenarg
is not an integer or non-empty arrayreturn null
whenarg
is a non-isohedral integer- if arg is integer (a die): treat
arg
as aarg
-sided die andreturn
a random integer between 1 andarg
(the roll result) - if
arg
is array of integers (a hand of dice): treatarg
as an array ofarg[i]
-sided dice andreturn
the sum of random results from each die roll.- if
arg[i]
is not an integer, it is ignored in the sum
- if
Walk-through
- TODOs: add support for single custom die
- array of strings or objects?
- TODO: add support for many custom dice
- is a sum needed?
- what is returned? an array of results?
New working title for the game inspired by King of Tokyo/New York: Calgary Coup. It might change later?
Up until recently I was planning on building the game after King of New York but Gord convinced me to use King of Tokyo instead because of the simpler feature set. He was obvs correct.
I went out an bought the KoT Dark Edition since I don't think I played it since before I learned about KoNY. I don't plan on playing it much, if at all, but the dice are distinctive enough that they'll come in handy for demos. Also, the box looks rad.
I just finished version 1 of the statechart and Gord was totally right. I don't think the number of states changes between versions (unless the current player can die after the dice are Resolved) but KoT has much simpler game logic than KoNY overall. But, it also adds the 3-of-a-kind dice logic for VPs that would make a good excuse to generalize a dice roller for something like Yahtzee.
Now I just have to build it...
Goal: Get journal items working on Freedom Insect.
- Current situation is a 404 error on:
http://localhost:3000/2022-05-03-code-from-cli
which should behttp://localhost:3000/journal/2022-05-03-code-from-cli
-
The problem is the relative link, but it's not. The current page address is:
http://localhost:3000/journals
and the anchor tag links to:
<a href="2022-05-03-code-from-cli">
but it directs to:
http://localhost:3000/2022-05-03-code-from-cli
when it should be:
http://localhost:3000/jorunal/2022-05-03-code-from-cli
-
Hard-coding the
/journal
directory into the template works but it's not optimal. Best guess is SK is overriding the url in the address bar somehow? Is it SPA by default?- There doesn't seem to be much in the way of answers. In fact, this Issue seems to show that this problem shouldn't be happening.
-
It was fun building a font selector thingy last night but the whole point was to help me decide on a font set for browsertherapy.com
. I've already done the work but forgot to do the fancy commit message to auto-close the Issue.
- Luckily, you can just paste the hash as a comment when you manually close the Issue and it'll link it. Noice! I always wondered how to do that.
Real name: browsertherapy.com
After adding placeholder pages for the top nav, I'm now in the tough situation of having to make actual design decisions. I'm too lazy to create actual wireframes and/or mockups, obvs, so I plan on winging it as usual.
I based the top page hierarchy on CSS Tricks, with a bit of flavour:
- Articles: basically date-centric blog posts;
- Guides: mature step-by-steps for things like Git and functions;
- Challenges: a place for the goal-oriented things like wrapping code into functions or centring a thing on the page.
For SK functionality, I'll go with a basic list entry/single item pattern and do something fancier for the home page. I'll probably also eventually need a spot to place the live-streams but I'll figure the schedule stuff out later.
I've recently re-discovered GitHub Projects Beta. I remember hitting a roadblock the first time I tried it but this last attempt was promising. I added some (possibly needless) cards to the backlog of Browser Therapy v2 to test it out.
I'm currently about to go down a rabbit hole with Google Font Install (poorly named and defined, I admit) and ot reminds me of an old idea for visualizing font pairings.
Problem: Picking good font combinations is hard!
- Google for some articles listing good parings (remains to be seen)
- Build a list of stylesheets that each set a google font paring for body text and headings.
- On a page of sample text, supply a dropdown menu that dynamically switches between the sheets.
This is a hacky version 1. Optimally, the system would be able to query the metadata from the Google Fonts API directly.
Goal: In SK, create a select
menu that sets a given font pair for body text and headings.
Plan:
- Set a default font set using
svelte:head
; - Move
svelte:head
code to a component and sethref
attribute to afontPath
prop setting the default value above. - Create an array of css file objects that point to an already-created list of font files.
- Set the
href
based on aselect
menu
Brute force:
- Question: which project to add this to?
- v0 on
tonygrimes.com
and move tobrowsertherapy.com
for v1.
- v0 on
- I added to my list of font pairs last night. migrating over... boom.
- Now, add default css file to
__layout.svelte
. - Almost went down a rabbit hole trying to get
$lib
work outside of an import. I'll just hard code the path for now. - Abril and Roboto are now the default fonts! Onto the
select
menu.- TODO: Check out Svelte Headless UI Component Library
- Great way to maybe upgrade the select element later?
- Also, he has really nice screen overlays.
- TODO: Check out Svelte Headless UI Component Library
- And, with the help of the Docs, I've got a working select menu.
Walk-through:
Optimizations:
- Component-ize this thing
Conclusion: I guess the real goal was to decide on a font pairing. This whole exercise was to build a tool to figure out that I think Elsie and Roboto a nice starter font set for browsertherapy.com
.
Project: Danger Carpet
- Goal: Refactor the original tutorial code that fetches the markdown files, BUT instead use page endpoints.
- Plan:
- Migrate some content from the legacy journal to create some dated markdown posts.
- Get it working with the original code
- Refactor it to use only page endpoints without the
load()
, if possible.
- Brute force:
- Added some posts. A format decision I need to make:
- Should there be a 1-to-1 for posts per day? For example, I might have two sessions on the same day that don't relate to each other.
- Option 1: one file per day named
MMM-MM-DD.md
- Option 2: multiple posts allowed per day but will have to add more to the file name, like
YYYY-MM-DD-some-title.md
- Option 1: one file per day named
- Not sure which I like best yet. One grievance is I need to repeat the date in the file name and in the front matter. It's a slight inconvenience but also rubs against my goal of lightening quick posting. Right now I just add a date to a mile-long README.
- Should there be a 1-to-1 for posts per day? For example, I might have two sessions on the same day that don't relate to each other.
import.meta.glob
is a nice SvelteKit feature. It seems like it'll be great for static page data.- Got the page endpoints working with few issues. The main obstacle was figuring out when a
return
value should be wrapped in{}
. This time, yes, wrap it as an object because it was an array. It unwraps once it's brought into the template. - Battery is running low so quitting for now...
- TODO:
post.path
links are coming up 404. Repeat this process for:path
posts.
- Added some posts. A format decision I need to make:
Thinking about data visualization.
Walk-through: Chartjs getting started
- Goal: Display a demo of chartjs in the centre of a Codepen.
- Plan:
- Use a CDN to import Chartjs;
- Find some code in the docs I can copy and paste to get a cart to show.
- Sprinkle some CSS
- Brute force:
-
The Docs reference the JSDelivr CDN
-
Copy and paste the HTML link into new Codepen
<!-- HTML --> <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
-
Paste this code underneath:
<canvas id="myChart" width="400" height="400"></canvas> <script> const ctx = document.getElementById('myChart').getContext('2d'); const myChart = new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); </script>
-
And we have a responsive
400px
x400px
canvas
element that is scrolling off the bottom of the screen.#myChart { display: block; width: 25vw; }
- This does not work. It seems the library is setting
width
andheight
imperatively based on screen width? - It looks like it's 100% the width of its container by default.
- This does not work. It seems the library is setting
-
To set the size and position, I just need to style a container:
<!-- HTML --> <div class="container"> <canvas id="myChart" width="400" height="400"></canvas> </div>
/* CSS */ .container { display: flex; align-items: center; width: 50vw; min-height: 100vh; margin: auto; }
-
- Walk-through
- Codepen: Hello Chartjs
- TODOs:
- Move the embedded
script
code to the JS Panel.
- Move the embedded
- TODOs:
- Codepen: Hello Chartjs
- Optimization
- completed TODOs
- Reflection
- Judging by my
git log
it took me about an hour to complete and optimize the ChartJS walk-through (while watching Fringe s02e15). - I'm tempted to get a Proof-of-concept using my GitHub
commit
tracker but I'm going to find and attempt a D3 tutorial. I don't think there's a Getting Started in the Docs.
- Judging by my
Treasure Hunt: D3 Tutorial Goal: find the quickest and easiest demo of the d3.js library using a CDN.
- If possible try to refactor for Codepen later.
- There are tempting examples in the Docs but you need to sign-in to fork them? It'd be nice to have a direct link to a repo.
- Abandoning the Docs for the moment. May Google find a way...
- A quick search for "d3 getting started" gave me this article:
- Short Guide to Getting Started with D3
- It seems pretty straight forward but doesn't provide any finished code.
- I think I can just copy/paste the code after "Putting Everything Together" this in a Codepen?
- Brute Force: Tutorial Attempt
- This tutorial still uses
var
and version5.9.2
. Yuck. - But at least it works on version
7.4.4
. - Styling is a little icky but it works.
- This tutorial still uses
- Goal: Create a commits/day graph using the data returned by the GH Activity API:
GET https://api.github.com/users/acidtone/events
- For this one, I'm creating an
index.html
file and adding it as a gist. - Plan:
- Get this Codepen to work in a stand-alone page.
- Fetch an array from the above API url;
.map()
the array to a count per day that matches the demo data.- Pull the d3 code into the fetch block and use the
.map()
array as the data source; - Cross fingers.
- Brute force
index.html
worked on the first try. nbd.- Now, the hard part. Figure out how to reduce the raw GH data to a commits/day array.
- Will be missing days that don't have commits but I'll figure that out later.
- Whew, I had to use lodash to group the array by date using
_.groupBy()
but I got it working.
- Walk-through:
- There's got to be a cleaner way to reduce the raw data array but that's a job for another time.
- Going to try moving the working code to Codepen.
- Optimize
- Done! Added a Codepen
Found this really great discussion about CSS and HTTP; the inflammatory named: Is .css a bad idea? Is inlining the way forward?
O.M.G. I just rediscovered opening a project in VS Code from the terminal with
$ code .
When zsh said, command not found
, I was getting ready for a battle. But apparently you can just set it up from within VS Code!
Anyhoo, it's time to get my personal site up, starting with the journals.
- coding and teaching set as Categories;
- tags (ex.
mdsvex
) for easy browsing; - dates for page title and sorting.
- two pages
- home
- post list
- pagination
- about
- "Behold! My stuff" would be great but David Parker took it first.
- links to Twitch, Meetup, Discord
- home
David Parker: sveltekit markdown nerd This dude's website is part of the inspiration, and conveniently created with SveltKit and MdSvex.
- davidparker.com
- He only wrote 3 posts but they look like good ones:
- He's also got a lot of great Youtube content.
- He attributes these mdsvex repos:
- c-bandy repo
- also "only" three posts, interestingly
- beautiful colors
- @mikenikles repo
- c-bandy repo
Project Goal: Get some content published on tonygrimes.com
that:
- demonstrates a code journal;
- can be sustainably updated;
- easy to reference past posts
Plan it out
- Install fresh SvelteKit with mdsvex
- Create First Post! in
/routes/journal
- step-by-step of the setup process
- Create index page
- Why I keep a journal
- README: Attributions
Brute force: notes A summary of the steps outlined in the above blog post for eventual inclusion in the first post(!)
- Create project:
$ npm init svelte@next tonygrimes.com
- Skeleton App
- No to the things
- Install the things
npm install
- Create
src/routes/journal/index.svelte
- Create
src/routes/__layout.svelte
- Skipped adding
Header
andFooter
components since neither are re-used in the project.
- Skipped adding
- Add
src/lib/styles/main.css
- Just adding a couple resets for now
- Import
main.css
into__layout.svelte
<!-- __layout.svelte --> <script> import '$lib/styles/style.css' </script>
- Skipping SASS, obvs.
- Install
mdsvex
and$ npm i -D mdsvex svelte-preprocess
- Configure
mdsvex
import sveltePreprocess from 'svelte-preprocess' import { mdsvex } from 'mdsvex' const config = { kit: { /* Kit options here */ }, extensions: ['.svelte', '.md'], preprocess: [ sveltePreprocess(), mdsvex({ extensions: ['.md'] }) ] }
- Created "First Post!"
- In an attempt to simplify the actual creation of a journal entry, I'm using only the
date
in file names and front matter.
- In an attempt to simplify the actual creation of a journal entry, I'm using only the
- Add a journal layout that auto adds the date as a level one heading.
-
Create
routes/journal/_post.svelte
// svelte.config.js /* Imports here */ const config = { /* ...Other config properties here */ preprocess: [ sveltePreprocess(), mdsvex({ extensions: ['.md'], layout: { journal: 'src/routes/blog/_post.svelte' } }) ] }
-
Add layout content
<!-- _post.svelte --> <script> export let date </script> <h1>{date}</h1> <slot />
- TODO: Process the date into something more readable.
-
- Uh oh: This blog post is using the
load()
method for the API. I think I'll stop here and figure out if I can work out how to do the same thing with the newer page endpoint feature.
- TODO: Walk-through of Svelte Components Using Custom Markdown Renderers
- Deep dive into how to parse markdown strings for custom patterns
- User Story: As a coding instructor, I'd like to add functionality to my code highlighter so that I can:
- select code sections
- add the page the code is from
- toggle between ES5/ES6, named/anonymous functions, options/composition API, etc
- Uses Stackblitz for code sharing:
- Custom Tokenizer And Renderer (forked)
- Custom Tokenizer And Renderer - Selector Version
- User story: As a Twitch streamer, I'd like to share finished code so that stream watchers can follow along at their own pace.
I'd love to be able to easily navigate to my project folders with bash shortcuts?
- How to navigate directories faster with bash
- Things this article taught me
cd -
goes to the previous directory.- Using it repeatedly will toggle between two directories! I can use this to toggle between a project and this journal.
alias ..="cd .."
adds a shortcut!!$
is an alias for the last argument of the previous commandmkdir -p make/new/directory cd !$
- Had to look up the
-p
flag; it's for creating nested directories
- Had to look up the
CDPATH
seems cool but the article doesn't explain it very well.- I stopped at
pushd
/popd
. They looked pretty cool, but maybe I'll revisit if I need to write a bash script.
- Things this article taught me
- Found: bash directory shortcuts
- I forgot I switched to zsh. It apparently has a feature called named directories
- Noice;
cd ~journals
now goes to my journals directory.
- Noice;
- I forgot I switched to zsh. It apparently has a feature called named directories
User Story:
As a coding instructor, I want to track the number of commits learners push so that I can give out Code Warrior trophies at the end of a course.
Goal
Set up a SvelteKit skeleton that logs public GET /activity
data to the console.
Plan
- Install latest SK skeleton
- Add page endpoint for my
GET /activity
as an unauthenticated use (if I can). - Output a count of my latest number of commits to a page.
Brute force
- Source: My Fave SK tutorial
- Stopping at the initial install to concentrate on the page endpoint
- Getting an irritating error in VS Code because it can't find
adapter-auto
- Now, how to use this fancy new page endpoint feature referenced in Rich Harris's latest SvelteKit update?
- Wow, I just copied the code from his screen using JSON Placeholder and it worked like a charm. That's nice.
- Wow, that was easy. SvelteKit is so awesome.
- Added a count of Push Events (
Array.prototype.reduce()
) and listed default 30 past events for my account.
Walk-through This was all surprisingly straight forward. But there are some issues with the implementation:
- This probably shouldn't be tied to a page endpoint. It was great to get something up and running quickly but the final counter should be a component(s).
- This is just listing one user: me. The final app needs to compile the numbers of multiple users in a given course.
- Given the API calls required for each user, a data store should be implemented to cache responses. That's a biggie.
BUT, there's some nice data provided in the response:
{
"id": "21512451971",
"type": "PushEvent",
"actor": {
"id": 6174466,
"login": "acidtone",
"display_login": "acidtone",
"gravatar_id": "",
"url": "https://api.github.com/users/acidtone",
"avatar_url": "https://avatars.githubusercontent.com/u/6174466?"
},
"repo": {
"id": 443250889,
"name": "acidtone/code-journal",
"url": "https://api.github.com/repos/acidtone/code-journal"
},
"payload": {
"push_id": 9741321869,
"size": 1,
"distinct_size": 1,
"ref": "refs/heads/main",
"head": "4f23c9160c52bc48b273cda5db7b54bad2d53523",
"before": "db05fa71fad1bc195d8225d6adcf6dc7c9b9dccb",
"commits": [
{
"sha": "4f23c9160c52bc48b273cda5db7b54bad2d53523",
"author": {
"email": "acidtone@tonygrimes.com",
"name": "Tony Grimes"
},
"message": "tweaks",
"distinct": true,
"url": "https://api.github.com/repos/acidtone/code-journal/commits/4f23c9160c52bc48b273cda5db7b54bad2d53523"
}
]
},
"public": true,
"created_at": "2022-04-28T06:40:10Z"
}
- TODO: Research the response returned for commits.
-
User stories:
As a coding instructor, I want to find commits with two parents so that I can evaluate if someone has resolved a merge conflict.
As an event organizer, I want to count alternating commits between two coders on a single repo so that I can see if attendees have successfully completed a pair code session.
-
Optimize
- Added user stories and a link to this post in the project README.
Given the dead ends with xTerm, I think I'll put the idea on the shelf for now. Here are some quick wireframes I made for the record in case I can find a collaborator with xTerm experience.
Screen 1: User is prompted to view the folder contents with
ls
.
Screen 2: User shows directory contents with
ls
.
Screen 3: User shows extra item info with
-l
flag.
Screen 4: User shows hidden secrets(!) with
-a
flag.
Project: Browser-based "game" for learning the command line
- Outcomes
- Navigate the file system using
pwd
,ls
andcd
- Create a mental picture of the file-system using visual cues of a traditional File Explorer/Finder
- Where are you?
- What is in the current directory?
- How do I get to another location?
- Navigate the file system using
- Research: File/directory and/or command line emulation in the browser
- CoCalc
- Full-ish featured shell in the browser but looks like overkill
- xTerm
- Looks promising! Still might be overkill, depending on how it works, but the install process looks pretty straight forward.
- Top Question: what does the file system look like? Does it have access to the system's? Can I create a virtual one for Follow the White Rabbit?
- CoCalc
Goal: First install of xTermjs
- It apparently requires npm to be installed; it's been awhile since I've tried using it for browser-based packages.
- It was a pretty straight forward install but key presses aren't registering in the web terminal. It feels like it needs a proper terminal to interface with?
- Found this issue that hints to me that I have to write the simple stuff like echoing keys back to the terminal :/
- This is good news I guess? Given my use-case, it's probably easier to add what I need rather than remove what I don't need.
TODO: Research some tutorials on how to add functionality to xterm.- Results: There doesn't seem to he much, aside from the documentation and a few examples on Codesandbox.
- I honestly don't get what this package does or is. I thought it would be something that you could throw in some connection info and you're good to go?
Goal: Add image handling to SAIT presentation template
- At first, I thought that SK's native image handling was what I wanted but it looks like you have to
import
individual images? - The SvelteKit documentation mentions two packages if I want to add images directly to the markup:
- Also found mention of vite-imagetools. Not sure if SvelteKit can grab new image URLs and do its magic?
- For example, if a
jpg
is processed into awebp
, how are SK links changed to use the new image?
- For example, if a
svelte-image
seems more mature and I'm not quite sure whatsvelte-preprocess-import-assets
does just by looking at the documentation.- This is a nice tutorial for
svelte-image
: live code: lazy loaded & responsive images in Svelte with svelte-image module- BUT:
- It's old: Apr 2020
- Was made for v0.1.9 (current is v0.2.9)
- It doesn't use SvelteKit
- BUT:
- This is a nice tutorial for
- Pickin's are a little slim when it comes to guides to image processing in SvelteKit:
Continuing with SAIT template
- Goal: Migrate image assets and icons
- Question: where to put static image assets in SK?
- Answer: inside the
$lib
- Answer: inside the
Continuing with SAIT template
- Through process of elimination (commenting code), the error is from the
badges
not being properly pass to the component- Setting a default fixes it, assuming it was just the students with no badges that were breaking.
- There are loops within loops but Badges now work (without images so far).
- TODO: Optimize the Badges component; remove
.find()
nested in.filter()
- Finishing commit
- TODO: Optimize the Badges component; remove
- Going to have to refactor the Social link code to work as a module
-
Kept running to a weird error where this code errored out:
item.group = info.group item.icon = info.icon
info.group
was undefined even though I confirmed it should work.
item = {...item, ...info};
- But this DID work? Maybe something SvelteKit specific problem with the way it keeps track of assignments?
-
- Done with the core of the components
- finishing commit
- TODO:
- Add image assets and Font Awesome icons
- Migrate CSS
-
Original: sait-wbdv.github.io
-
New repo: finals
-
First question: where should static json data live in SK?
- Doesn't look like there's an official convention. Going with a data directory.
- Going to import js instead of json.
- Should
data
go into thelib
directory?- unclear from the documentation what should go into
lib
besides modules - could use
$app/stores
but it looks like that will increase the complexity of the app. - Going with
$lib
for now
- unclear from the documentation what should go into
-
TODO: Convert linklist.js into a Svelte component.
-
Error importing the roster and finals list:
Module '"/Users/tony/Documents/sait/wbdv/finals/src/lib/data/f21/finals-f21"' has no default export.js(1192)
- Looks like there's a requirement for default exports?
- Apparently so.
-
Next step: Convert the card templates into components.
- Leaving that for later. Time for a break.
- finishing commit
Goal: On to the next step - creating a card component.
-
Just looking at the imperative DOM code in my vanilla JS makes me shiver:
const card = document.querySelector('#card').content.cloneNode(true); // Name, tagline card.querySelector('header').innerHTML = student.label; if (student.tagline) { card.querySelector('p').innerHTML = student.tagline; } else { card.querySelector('p').remove(); }
- Never thought I'd ever jump on the view framework bandwagon but SK seems like the right balance of weight to benefit. Queue cold Hell.
-
At least I used HTML templates so it's kinda declarative:
<figure> <img src="" alt="[name]"> <figcaption> <aside class="badges">[badges]</aside> <header>[name]</header> <p>[tagline]</p> <footer class="social"> </footer> </figcaption> </figure>
-
Having trouble with props. Getting this error when trying to loop through
students
and pass the data to myCard
component:[HMR][Svelte] Error during component init: <Index> proxy.js:15:11 TypeError: can't access property "$$", cmp is null
- First of all, what fuck kind of error is this?
- I'm assuming I'm not passing props down to the component correctly?
{#each students as student} <Card student={student} /> {/each}
- Never mind. It's working now. I guess I have to reload after a hard error.
-
Figuring out how to handle the badges and social links.
-
Loops within loops. What's "better" for rendering alist of badges/social links for multiple students?
- an array of objects
- an object of objects
- some kind of intermediary step?
-
I basically need to "reduce" the full array of badges into just an array of badges for a particular student so it can be handled by a simple
#each
loop.- I could do this with a
.map()
but the info is split between two arrays?
- I could do this with a
-
Trying to figure out these cryptic errors:
at eval (/src/lib/components/Badges.svelte:14:38)
Badges.svelte
only has 10 lines of code. wtf.
-
Giving up for now.
-
- I like the idea and general layout. Not as much into the colours
- Asymmetry is great, slanted page dividers is an oldie but a goodie.
- Love the colours, slight gradient combined with a minimal vector logo
- Would be pretty easy to do with alternating grid cell alignment.
- Might make for a nice intro card to an activity/lesson/concept
- Would love to figure out how to make more complex cards that display code.
- Great implementation of changing options to see different code variations in a tutorial
- Could also work for
- ES5 functions vs fat arrow syntax
.then
/.catch
vsasync
/await
- Love the table of contents
- Is a nice example of documentation conventions.
- Could make a nice curriculum summary for a course?
- Simple example that could work for notices: warnings, pro-tips, etc.
- A little boring (not Mandy's fault; not her page) but the minimal nav for a video page could come in handy
- Just a cool example of how you could use an SVG instead of a horizontal rule.
Goal: be able to add custom classes to non-container elements (already handled by remark-container
)
-
main worry is that the
{}
syntax ofremark-attr
will conflict with Svelte template syntax. -
Continuing work on sveltekit-mdsvex
-
Plan:
- Add test code to
/tests/markdown
followingremark-attr
sample code - Install
remark-attr
to SK and cross fingers
- Add test code to
-
Example syntax for test page:
### This is a title {style="color:red;"}
Npm stand for *node*{style="color:red"} packet manager.
-
Still new with SK. Going back to the original MD SK tutorial to remind myself how to add a
remark
plugin.- Turns out it doesn't cover plugins? I guess I just figured it out last time:
-
install the plugin
npm install remark-attr
-
Import it into
svelte.config.js
:import attr from "remark-attr"
-
Do I add it to
remarkPlugins
insvelte.config.js
?
-
- Turns out it doesn't cover plugins? I guess I just figured it out last time:
Thinking about a blog that:
- Displays code really well.
- hightlight code selections (inline and line range)
- show relevant page name as heading
- Can embed content the major vendors
- Shows a great table of contents
Requirements:
- SvelteKit
- Markdown
- mdsvex
- definitions
- embeds:
- Codepen
- Youtube
- Gists
- Stack Overflow?
- mdsvex
- Notices
- Code highlighter
- Prism?
- R&D: how do code highlighters work?
- Easy image workflow.
- screencaps
- optimization
- svelte-image?
Goal: Install and start MongoDB locally; just in case I need it for a Mongo review session tomorrow (planning on focusing on Atlas).
- Found this tutorial that recommends Homebrew: Installing MongoDB on a Mac
- I have a love-hate relationship with Homebrew. I always forget where it installs things (Cellar?) and I remember having to deal with duplicate installs when software overlaps with a package that comes with the mac (like php).
- Current Homebrew version is 3.2.6; current is 3.4.5.
brew update
; probably shouldn't be doing this on pub wifi... - Ran into my first problem from the tutorial:
- "After downloading Mongo, create the “db” directory. This is where the Mongo data files will live. You can create the directory in the default location by running
mkdir -p /data/db
" mkdir -p /data/db
returnedmkdir: /data/db: Read-only file system
. No/data
directory exists. I'm already close to giving up on local installation. More trouble than it's worth.-
googled the error and found this post. It gives two methods to work around the error, but the author doesn't mention (or know) the root cause.
-
Going with Method 2 and storing the data in my home folder. Not sure why; just cuz.
-
Created a
~/data
directory in my home folder and then tried running:$ sudo mongod --dbpath=/Users/tony/data
and, of course, received the error:
sudo: mongod: command not found
In general, if I have to add a
PATH
to my environment variables, I'm out. This isn't 1999. -
Giving up on a local installation (yet again). Going to focus tomorrow's session on Atlas.
-
- "After downloading Mongo, create the “db” directory. This is where the Mongo data files will live. You can create the directory in the default location by running
Goal: Figure out the pattern behind the flexbox albatross
- Articles
- The Flexbox Holy Albatross
-
Critically,
min-width
andmax-width
overrideflex-basis
.
-
- The Flexbox Holy Albatross Reincarnated
-
lol,
min-width
andmax-width
aren't even needed:.container { display: flex; flex-wrap: wrap; --margin: 1rem; --modifier: calc(40rem - 100%); margin: calc(var(--margin) * -1); } .container > * { flex-grow: 1; flex-basis: calc(var(--modifier) * 999); margin: var(--margin); }
- TODO: move
40rem
to a CSS variable. - Can sprinkle some >1
flex-grow
to create variable-width items
- TODO: move
-
- The Flexbox Holy Albatross
Wishlist: A collection of tutorials tagged by the technologies and versions used.
- title: Let's learn SvelteKit by building a static Markdown blog from scratch
link: https://joshcollinsworth.com/blog/build-static-sveltekit-markdown-blog
tech:
- svelte@3
- sveltekit@next
- mdsvex@0.10
- User stories:
- As a learner, I want to save a great tutorial I just found, so that I can easily find it later.
- As a tutor, I want to collect a library of learning materials, so that I can easily assign homework to my clients.
- As a teacher, I want to filter out old tutorials, so that my students don't get confused by references to older syntax.
- As a school, I want to filter for tutorials by technology, so that I can quickly generate materials for a particular course/program.
- Could also do the same thing with CSS properties, HTML elements and JS features?
- How do you host it?
- Could it be a file database? markdown with front matter?
- Add the complexity of Strapi?
- Sanity.io? Possible to convert to Strapi later?
- Collections
- Resources
- title
- author
- link
- slug
- breakdown
- Authors
- name
- slug
- socials: gh, codepen, etc
- Technologies
- name
- slug
- homepage
- Resources
Goal: Create a slides directory in SvelteKit (SK) that wraps RevealJS around all files inside it.
- I just did this today with Nuxt (both 2 & 3) with mixed results. I've got high hopes that this will be easier with SK.
- First decision: do I carry on with the md-blog project or create a new one?
- I don't know what's ahead of me so I'm going to keep it simple: implement reveal site-wide and figure out how to do it on the route level later.
- If that works: implement markdown slides.
- Got it working with Ash and Jess's help but the .__nuxt container needs an explicit height.
- Conclusion: now sure what's breaking but it feels like the nuxt container is hiding the slide content by becoming zero height. It could also be a tailwind issue?
Goal: Deploy md SK skeleton site to Netlify
- Going off the official Netlify docs.
- And it worked after I removed
config.kit.target
. The documentation needs to be updated.
Goal: Set up a boilerplate Svelte site with Markdown support
- Following this tutorial: Let's learn SvelteKit by building a static Markdown blog from scratch
- Skipped the SASS portion
- So far so good; MDSveX installed like a charm
- After md support added, VS Code is showing syntax squiggles for the Svelte code
- PrismJS is working by default with MDSveX but there are no highlight styles.
- Problem: How to add
prism.min.css
from a CDN svelte.head
seems to be the Svelte way of adding alink
element to thehead
of a page. The official tutorial shows adding<svelte:head>
toApp.svelte
that file doesn't exist in the skeleton site that's been generated.- Solution: Added the
link
to__layout.svelte
using<svelte:head>
and it worked!svelte.head
seems to be built into SvelteKit. - TODO: Add some remark plugins
definition lists[remark-deflist
]element classes[remark-attr
]wrapper elements['remark-containers']
- Problem: How to add
- Using the Git page from WBDV as a sample blog post.
- TODO: Figure out where/how images are handled in SK (for error screencaps)
- Where are static assets kept?
- How are relative links handled?
- Does SK have any fancy features for image handling?
- TODO: Figure out where/how images are handled in SK (for error screencaps)
- TODO: Add
/categories/index.svelte
page to list all categories - Adding autoprefixer requires
svelte-preprocess
, which I skipped because I'm not using SASS so I'll have to go back and install it.- Pretty straight forward...
- TODO: Add Excerpts to the blog index page
- TODO: Add Custom error page
- TODO: Preload routes
- Done!
Goal: Install remark plugins for extended markdown syntax parsing.
- Mostly using the MDSveX Docs
- Definition lists:
remark-definition-list
doesn't seem to work anymore butremark-deflist
does.
- Wrappers:
remark-container
works as advertized- Tried
remark-directive
for deeper syntax support but the{}
syntax seems to interfere with Svelte. I'd really like to get this one working. Might require an Issue submission to theMDsveX
repo.
- Table of Contents
- Leaving this for later. Can be done with
remark
and/orrehype
. Requires more research.
- Leaving this for later. Can be done with
- Codepen Embeds
- The HTML method from Codepen's copy/paste utility breaks during build but the iFrame option seems to work.
Goal: Mood board practice
- Theme/product/company ideas
- Rake Bomb Landscaping Inc.
- Napkin Candy Designs
- Toy Ticket Events
- The Rain Whistle
- Team Shadow (D&D Guild, probably mostly made up of Rogues)
- Vomit Drum (metal band)
Research: Design in Figma
- Mood boards are cool
- How to Mood Board for Web Design by Jesse Showalter
- Moodboards should contain:
- Colour palette
- Typography
- Textures
- Patterns
- Photo selections
- Misc
- Types of mood boards
- Strict mood board
- Messy mood board
- Pin board
- Style Tile
- Moodboards should contain:
- How to Prepare for a Brand Identity Mood Board
- How to Mood Board for Web Design by Jesse Showalter
- Compilation of Mood board contents from the above and some other videos:
- Colour palettes
- Typography
- Photos and illustrations
- Textures
- Patterns
- Logos
- Misc: anything that directly relates to the project
Goal: Find a router for OPNSense
- Apparently, Memory Express isn't what it used to be. Every potential router brand that will run pfSense or OPNSense is not found. The only appliance that comes close are Ubiquiti brand, which have a bad reputation. Shame.
- Found this Reddit thread: Best little hardware device for OpnSense/PFSense?
Goals:
- Secure my local network
- Potentially open network so I have access to my files outside my home
- Learn network shit
- Create a base setup where I can:
- sniff packets coming from the Nest
- sniff packets in general
- Unicorn: create a Youtube history of videos I've watched in the Shield/Roku/etc
- Goal: reference for educational vids I can use for lesson plans/activities/etc.
Results:
- pfsense vs opnsense
- pfSense® vs OPNSense - which firewall OS is better?
- I had no idea there was nerd-drama between pgSense and OPNsense. Juicy.
- It seems like I can go either way but the (apparent) behaviour of the pfSense community pisses me off enough to offset the bigger ecosystem. Going to try OPNSense!
- pfSense® vs OPNSense - which firewall OS is better?
- load balancing
- How can you survive without a load balancer in every home?
- Still not convinced I need a load balancer but if I do...
- I don't think I'll go with the free version of Kemp? I think HAProxy is the way to go if I can find a NetworkChuck-level tutorial to walk me through the process. Worst case, I guess I can take notes on NC's video and figure out how to do it on HAProxy.
- How can you survive without a load balancer in every home?
- hardware:
- What hardware to buy for OPNsense router in 2021
- None of the routers on this list are available at MemEx. In fact, I can't find any non-wifi routers other than Ubiquiti (which seem to not have a good following)
- TODO: Find a good router that can run either OPNSense (preferred) or pfSense
- What hardware to buy for OPNsense router in 2021
Goal: Looking for js-based libraries that can be used as CDN examples.
-
The requirements of the library are still vague but here's what I can think of so far:
- A minimal amount of JS knowledge is required to give us a starting point for JS lessons:
- variables and assignment
- function invocation
- object literals
- The library should provide immediate value to the coder installing it;
- The difficulty of the library should be appropriate to the coder's skill level
- A minimal amount of JS knowledge is required to give us a starting point for JS lessons:
-
Revealjs
- This is the first library I thought of and most of the installation was review for me.
- The installation options do not include CDNs
- The simplest option, Basic Setup comes with a lot of extra files and directories:
/dist
plustheme
/plugin
gulp.js
LICENSE
- etc, etc
- The other options are Full Setup ("Recommended") and Install from npm
- What seems to be missing is a "blank boilerplate" install using a CDN?
- Question: Is there a simple config/setup option that would make a good introduction to JS?
-
The Markup Guide has a bare bones set up that could make a good intro to invoking a function:
<html> <head> <link rel="stylesheet" href="dist/reveal.css"> <link rel="stylesheet" href="dist/theme/white.css"> </head> <body> <div class="reveal"> <div class="slides"> <section>Slide 1</section> <section>Slide 2</section> </div> </div> <script src="dist/reveal.js"></script> <script> Reveal.initialize(); </script> </body> </html>
-
The Config Options could be a good intro to object literals:
Reveal.initialize({ controls: true, rtl: false, navigationMode: 'default', preloadIframes: null, autoAnimateEasing: 'ease', autoAnimateDuration: 1.0, autoAnimateUnmatched: true, autoAnimateStyles: [ 'opacity', 'color', 'background-color', 'padding', 'font-size', 'line-height', 'letter-spacing', 'border-width', 'border-color', 'border-radius', 'outline', 'outline-offset' ], autoSlide: 0, // Transition style transition: 'slide', // none/fade/slide/convex/concave/zoom pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, hideCursorTime: 5000 });
- complex value types: object literal as the container, array as a config option
- boolean, string, number and null as primitives
-
The
Reveal.configure()
could be used to introduce methods (and serve as abutton
assignment for triggering events).
-
- The bare bones example they give is all that's needed to get things started, but I'll use a CDN so it will fit in a Gist.
Goal: Import a subset of terms into Sanity
Plan:
- Convert a terms file to ndjson.
- Import to sanity using the cli.
- Add some categories to the terms using studio.
- Export the result.
- Figure out how to structure a full import.
Brute force
- Materials from last session
- Imports seem to complete without error but they don't show up in studio.
- I've had to try importing a few times after changes but I get
Document by ID "global" already exists
errors the second time around.- I got away with the first change by changing test-import to terms but now I've got to try deleting
production
? - I need to figure out how to burn the farm.
- I got away with the first change by changing test-import to terms but now I've got to try deleting
What's the best process for burning the farm and importing my terminology data from scratch?
- If I have a list of terms in YAML, how do I import them into Sanity so that they use categories that I've already entered into Sanity?
- What are the CRUD implications of referencing categories in an import (if possible)?
- Looking up bulk imports, found in the last session.
- I'm learning things! There's a such thing as NDJSON - Newline delimited JSON. So, no: it doesn't look like Sanity supports yaml imports.
- yaml -> json -> ndjson will need to be a thing.
- From the docs:
- Documents should follow the structure of your data model:
- most importantly, the requirement of a
_type
attribute. - the
_id
field is optional – but helpful – in case you want to make references or be able to re-import your data replacing data from an old import. _id
s in Sanity are usually a GUID, but any string containing only letters, numbers, hyphens and underscores are valid.- Can slug act as effective ids? How about overloaded terms like "view" or "property"?
property-object
vsproperty-css
- Maybe there's a way to auto-append categories to the term to make them unique(ish)?
- I can't think of an instance where a term with the exact same categories would be different. It just means that categories would need to be used for repeating terms.
- Can slug act as effective ids? How about overloaded terms like "view" or "property"?
What's the best starting config for a Terminology module?
sanity init
the blog template because that's what Kapehe did- Sniff around the template and see what's what.
- Depending on what I find out, try creating a terms schema.
- What's the easiest way to import bulk data, preferably YAML?
- Tried a few video tutorials and Kapehe comes up as a guest on a few YT Channels. Her script is the same for most so I'm following the one from Traversy.
- Installing a vanilla blog:
$ sanity init
- have to login
- Project: hello-sanity
- Dataset: production
- Template: blog
- Kapehe says this has a schema but no data. The others have sample data.
- The README links:
- Read “getting started” in the docs
- Check out the example frontend: React/Next.js
- Read the blog post about this template
- Join the community Slack
- Extend and build plugins
- At first glance, the directory is pretty light. That's a good sign.
- It looks like the
schemas
directory is where all the action is. - Question: how do I boot this up locally?
- The docs look pretty polished so far: Getting started with Sanity CLI
sanity start
- The docs look pretty polished so far: Getting started with Sanity CLI
- I just realized
sanity init
installs everything in thepwd
. Moving into a directory... sanity start
works as expected. But now I have questions about where to go from here.- What's the relationship between
localhost:3333
and the data? - I've just started a
hello-sanity
project. Is this using up quotas on my free Sanity account?- Looks like I'm limited to two datasets.
- How many projects can I set up with
sanity init
before I have to pay? So far I havehello-sanity
andbrowser-therapy
but the second has no studio code installed.- Ahhh, that's what
production
is: the dataset. So it looks like I can choose my dataset when I build a new project.- So what if I delete schemas that another project depends on?
- Ahhh, that's what
- What's the relationship between
- Where do I store data for the terms project?
production
?- Where do I put the
hello-sanity
data? - It doesn't look like I can rename the production dataset.
- Maybe the blog schema is general enough that I can just keep those and add the terms schema to it. Whatevs, I can just burn it all and create a new account with my GH login.
- I'll try adding terms and maybe move the project out of
_hello
once there's data/code that I don't want to lose.
Goal: add terms schema
- fields:
- term
- description
- slug
- any other Sanity fields that seem handy
- First decision: what schema type do I use?
- Schema Types Docs
- Looks like
document
is the base type. Good enough for now.
- Next decision: what field type should I use for term description?
- Is not a string, but
blockContent
seems like overkill. Is there a middle type? - Kinda? There's the
text
field type but it looks like allblockContent
is, is an array of specialtext
fields. So the question is do I want to use formatting like bold and italic? - Given that I still need to import all these terms, I'll go simple and use
text
. Maybe there's a plugin to add markdown to the import and useblockContent
later.
- Is not a string, but
- OK, created
./schemas/term.js
and it's not showing up in Studio. Looks like I have to register it...- Boom. Just have to add it to
./schemas/schema.js
. Pretty slick.
- Boom. Just have to add it to
- I think I'm going to stop here for now and look into bulk imports next session.
- Links from Ellie's guest speaker session
- Laws of UX
Laws of UX is a collection of best practices that designers can consider when building user interfaces.
- Frontend Mentor
Solve real-world HTML, CSS and JavaScript challenges whilst working to professional designs. Join 282,931 developers building projects, reviewing code, and helping each other get better.
- Laws of UX
- First class of
#winter-2022
. Totally forgot to add markdown to W1W Prep :/- search: "github flavoured markdown cheatsheet"
Goal: Continue to add content to the Library, and test the _.vue
file for Unknown Dynamic Nested Routes.
- Time to try this Nuxt feature out to easily migrate last semester's content to an expanded Library directory:
- breakdowns: synopsis files for individual articles, videos, tutorials, etc (aka resources).
- takeaways: summaries of topics that aren't associated with one resource.
- tools: Summaries of cheats, tutorials and documentation for VS Code, bash apps, Firefox, etc.
- if the
_.vue
file works as advertized, I should be able to add markdown to thecontent/library
subdirectories without adding sistervue
components to thepages
directory. - starting commit
Goal: Figure out how to get Unknown Dynamic Nested Routes working.
- Specifically, I want this page (also my initial commit) to render when I enter this url:
/library/breakdowns/making-clickable-elements-recognizable
- plus, I don't want to fiddle with the
pages
directory if I organize these md files in sub directories.
- Recap: got it working pretty quickly.
_.vue
files are a nice feature (for now).
- Repo: winter-2022
- Live Site TBD (to be deployed)
- Migrations:
- Schedule -> Home page
- Home page -> Test Page
- f21 ->
- House Rules
- Library
- Research: Takeaways
- do slugs include directory segments?
- Schedule:
- Dasa day fix
- Add two 201 days!
- add home work to
- 201 day 1 and 2
- 270 day 1-4
- 262 day 1-5
Goal: Knock as many down as I can and throw Assignment ideas in the parking lot
- starting commit
- Starting to get the hang of Nuxt Content.
- Taking a break. commit: migrated page content
- Back from break. Added checkboxes to the todos.
Goal: Add Homework and Labs to 201 Lessons
- Plan
- Migrate: Orientation -> Day 0
- Test homework component: Add issues as needed
- Create Labs content directory
- Day 1: Follow the white rabbit
- Day 2: Project: Publish a webpage with Git and GitHub Pages
- commit: 201 day0
Goal: Add Homework
- TODO: Change "Homework" to "Prep" or similar.
- commits:
Goal: Create a store
if a flat chronological array of lesson slugs.
-
Video: Vuex Store with Nuxt and Vue
-
/store/index.js
// state export const state = () => ({}) // getters export const getters = {} // actions export const actions = {} // mutations export const mutations = {}
-
-
Video: Learn Vuex in 30 MINUTES! (Vue JS 3)
-
/store/index.js
import { createStore } from 'vuex' export default createStore({ state: {}, mutations: {}, actions: {}, getters: {}, modules: {} })
-
-
These two videos show different ways to create a store but then I realized:
- There's Vue 2 and 3
- There's Veux 3 and 4
- turnes out
createStore()
is newer and probs won't work with our site
- turnes out
- I'm creating a store in Nuxt 2
-
Search: "nuxt 2 vuex"
- Nuxt Docs: Store directory
- These docs give a pretty decent summary of what I need to do.
- Nuxt Docs: Store directory
-
-> Rick
-
Goal: Set up a
/store/index.js
file -
Sources:
-
Been staring at nonsensical articles and documentation for awhile. I've gotten this far
- How do I initialize these
store
hooks to invokegetLessons()
? - How do I load the data just once when the app loads?
- Once the data is loaded, how do I access the
store
from the component?
- How do I initialize these
-
I'm giving up on the page nav for now. I posted to Pixels but no response yet.
Goal: Master schedule by week array
- After talking with Ash, I'm going to try a quick and dirty brute force of a Schedule by week that will work in the template
- Plan
- Create an additional array of weeks, each with lesson list
- export that array to the
template
- Output component with two
v-for
(one for weeks and the other for lessons)
- Brute force: initial commit
- I've got the week array mostly working but there's a bug that I think is caused by the hacky way I calculated weeks. But that's good enough to move on.
- TODO: Add new issue about the bug
- -> Morty
Goal: Learn some v-for
, and output the buggy nested array I just built :)
- I'm weak on
v-anything
atm so setting up a new branch with a testv-for
- Noice. Got it working; just have to figure out how to output
index + 1
in the heading- Search: "v-for index"
- Noice! In hindsight, maybe a branch wasn't needed.
- -> Rick
- Ugh, now I have to merge and delete the branch
- merged commit
- Aaaaan how do I delete a remote and local branch again (for the 50th time)?
-
Search: "git delete branch"
-
Top result (again): How to Delete a Git Branch Both Locally and Remotely
// delete branch locally git branch -d localBranchName // delete branch remotely git push origin --delete remoteBranchName
-
- Cleaned up the code and added the date
Goal: Output pretty dates on the Schedule
- research: content:file:beforeInsert
- cleanup:
beforeInsert
is only for saving data to the file beforeParse
is for changing data before it's used in the app but you only have access to the raw front matter.
- cleanup:
- Given the limitations of the Content module, I ended up just explicitly setting the time (adjusted for UTC) on every lesson.
- I find that the Content module breaks down quickly for end cases.
Goal: Give individual lessons access to a global index of lessons for Prev/Next links.
-
Research: As soon as I need data that is accessed by mutliple components, it looks like I need state and
vuex
is how I do it. -
Search: "nuxt state mutation patterns"
-
Top result: Scalable state management with Vuex and Nuxt.js
- Gotta be honest, I didn't read it, yet. One of the images is from the docs so I went there first: What is a state management pattern?
- From there the Vuex docs gave me When Should I Use It?:
"A simple store pattern may be all you need"
-
Pet Peeve: I'm still reading through the previous link and sample code like suffers from a common fault that I know I'm guilty of (and would like to rectify):
var store = { debug: true, state: { message: 'Hello!' }, setMessageAction (newValue) { if (this.debug) console.log('setMessageAction triggered with', newValue) this.state.message = newValue }, clearMessageAction () { if (this.debug) console.log('clearMessageAction triggered') this.state.message = '' } }
-
This is a bad example (for me) but a beginner will ask the question: "do I need to name it
state
" or can I choose my own name?- There are soooo many examples of framework code where this applies, particularly to lifecycle hooks. For example,
setup()
(I think?) is now a Vue 3 hook but how does the beginner know that it's a reserved keyword?
- There are soooo many examples of framework code where this applies, particularly to lifecycle hooks. For example,
-
TODO: Bring this up with Ash (and team) about how to have our lessons/documentation take this into account.
-
Another example:
var vmA = new Vue({ data: { privateState: {}, sharedState: store.state } })
- does
data
need to be nameddata
?
- does
-
Goal: Test DayJS in Nuxt
-
Ash installed
$dayjs
as a build module and I'm figuring out how to use it to solve the timezone issues. -
Last resort: If I can't get tz to work, I'm just going to explicitly set a full UTC datetime string as
lesson.date
in all the markdown files.- If you can't tell, I'm losing faith in Nuxt. Yesterday's rage still lingers.
-
setting the timezone in the config so far has no effect on
item.date
output from Nuxt Content. -
According to the timezone plugin docs I might have to explicitly extend DayJS:
var utc = require('dayjs/plugin/utc') var timezone = require('dayjs/plugin/timezone') // dependent on utc plugin dayjs.extend(utc) dayjs.extend(timezone) dayjs.tz("2014-06-01 12:00", "America/New_York") dayjs("2014-06-01 12:00").tz("America/New_York") dayjs.tz.guess() dayjs.tz.setDefault("America/New_York")
- First of all,
var
? How old are these docs? - Going to try to use
dayjs.tz.guess()
to confirm the set timezone. Ash already listedutc
andtimezone
as plugins in the config but how do I use.extend(utc)
from within Nuxt? - DayJS might not support global plugins but I just imported locally to the schedule component. It's outputting
America/Edmonton
as the timezone but the problem still seems to be the conversion Nuxt applies to front matter dates. DayJS doesn't seem to be used for this conversion. - It might be time for the last resort...
- First of all,
Goal: Add some hierarchy to the Schedule.
- Plan:
- Add some draft titles to the lessons for testing.
- Remove duplicate "Day X" from lesson titles (if they're allowed to be empty)
- Add "Week X" headings to the for loop.
- Code Spike: how to add dynamic containers for each week from a flat
v-for
loop? - It might be easier to build weeks into the data structure.
- Code Spike: how to add dynamic containers for each week from a flat
- Content added:
- Now to add some "Week X" headings. This may quickly turn into a pair session with Ash.
- I notice that the
v-for
is inside aul
where it outputs theli
s. I can't immediately visualize how to add conditional headings and list containers to a flat loop. - I think my time is better spent adding pagination to the lesson pages.
Goal: Research - what's the best way to add Nuxt pagination for post dates in the future?
- Search: "nuxt pagination"
- First red herring: Adding Pagination With Nuxt Content
- I tried cloning the same blog but it won't boot.
- Moving on...
- First red herring: Adding Pagination With Nuxt Content
- Most of the tutorials are specific to blogs whereas we're an edge case.
- dates are often in the future
- no pagination nav needed besides Prev/Next links
- content is spread out over multiple content modules and manually concatenated.
- I think the easiest solution would be to simply add
prev
andnext
properties to thelessons
array.index - 1
andindex + 1
should give the loop access to thedir
andslug
properties.- Problem: how do we share the dynamic data from
schedule.vue
with the individual lessons?
- It's looking more and more like we need a master store for the program schedule that will power the Schedule and lesson Prev/Next nav?
Goal: Migrate layout templates from fall-2021
to winter-2021
- Trying to copy the structure as much as possible so I removed the separate primary and utility nav. Merging into one primary nav is good enough and will let me keep most of the styling.
- Pair code with Ash: add Utility nav later
- Question: when to use
nuxt-link
?- Search: "nuxt-link vs a"
- A: nuxt-link is for all internal links, use
a
for external links
- Question: what goes into
static
and what goes intoassets
?- Search: "nuxt assets vs static"
assets
is processed by Webpack but what about Vite (maybe doesn't matter)?
- Question: How do I link to internal images?
- Search: "nuxt img src"
- Looks like
~/assets
is the way to go
- Moving on to adding css to the
head
usingvue-meta
(I think).- Noice. Ash links to the docs again.
- Hooking up the css was almost trivial.
- I know I said I was going to keep the original design of the header but I can't help myself.
- Inspiration: CSS Tricks
- It's a nice, compact design that runs fro end to end of the page. That'll leave room for the extra links and the Utility nav can go to the far left.
- Inspiration: CSS Tricks
- Done!
Goal: Split the WBDV schedule into Weeks
- Repo
- Issue
- recap: installing Luxon was problematic and DayJS is an optional build module that might work. BUT, I think I'm just going to do the Week math manually and maybe refactor for a library later.
- Got to find the article that gave me the math before:
- Search: "js date week number"
-
Top result: Get Week Number of the Year in JavaScript
-
relevant code example from article:
currentdate = new Date(); var oneJan = new Date(currentdate.getFullYear(),0,1); var numberOfDays = Math.floor((currentdate - oneJan) / (24 * 60 * 60 * 1000)); var result = Math.ceil(( currentdate.getDay() + 1 + numberOfDays) / 7); console.log(`The week number of the current date (${currentdate}) is ${result}.`);
The code seems to be based on the 1st of Jan and then defining a week as +7 days. The Schedule only needs to count starting on the first Monday as Week 1.
-
- Search: "js date week number"
- The logic shouldn't be too far off from above. Pseudo-code:
- Loop through sorted list of days in Schedule
script
. - Define the start of Week 1 as the Monday of the first date in the list (if first day is a Tuesday, use the day before)
- Create date object of this Monday as
startDate
- Set
week
iterator to 1. - foreach date:
- Subtract
startDate
fromcurrent
- divide by 7 days
- round down
- If: not equal to
week
iterator, setweek
to new value - set
item.week
toweek
- Subtract
- Loop through sorted list of days in Schedule
- Once the week is set for each item, it should be straight forward (hopefully) to build Past, Current, Upcoming weeks into the Schedule
template
. - starting commit
- -> Morty
- Added link to pair session with Ash!
- Back to weeks thing...
Step 1. Declare base week
and startDate
firstDate
is better thanstartDate
?- Oooo, I almost got distracted from the goal by trying to set the lesson date to 8am. Midnight is good enough for now.
Step 2:
- Search: "intl date day of week"
- I really want to use
Intl
butDate
object is good enough for now
- I really want to use
- Managed to maybe figure out some really sloppy code but I'll test after I finish the steps. Cuz I'm crazy like that.
Step 3. Else: subtract startDate
from currentDate
, divide by 7 and round down (currentWeek
)
-
I'm pretty proud of this one. Steps 3 and 4 complete in one line:
week = week + (floor((currentDate - firstMon) / 24 / 60 / 60 / 7))
-
Time for the reckoning: let's boot this puppy up...
ReferenceError: floor is not defined
- lolz.
- Well, week 1 is correct :)
- the Date Object is kicking me in the ass.
-
Good to know - front matter dates in YYYY-MM-DD are converted to the following in Nuxt Content:
2022-01-10T00:00:00.000Z
- TODO: Set the timezone in Nuxt/Vue config
- TODO: Possible to set default start time (8am) to lessons?
-
taking a break
-
-> Rick
-
Just realized the message for the above commit is not appropriate. Instead of "mid-session transfer to Rick", it should have been more descriptive of the code, like "buggy - added first draft of Schedule by Week"
-
Logic error 1:
week
was proceeding from 1, to 144, to 430, to 589 but not sure whyweek
is now returning NaN after playing with some date formatting- going to try figuring out how Nuxt Content is affecting my code with it's date object
- it looks like dates are converted to a UTC string?
- My math is also off for subtracting a day's worth of seconds if the first day of class isn't a Monday:
- search: "js new date minus 1 day"
- top result: How to subtract days from a plain Date?
- it worked!
-
Logic error 2
firstMon
is inheriting the time that the code is running- going to explicitly set the time to 8am when creating
itemDate
- Fixed, but it's needs optimization
-
Logic error 3
- Monday is turning to Sunday because of timezone (-7 hours)
- This was such a pain in the a$$! I tapped out and just added a day to
itemDate
to compensate for the timezone. - The problem: Nuxt Content converting YYYY-MM-DD to a date object in UTC. Very frustrating.
-
The proper
week
is now inserting into the lesson objects.
Walk-through
- cleaned up commit
- Will eventually fix a potential bug with adding a day for timezone but not today
Reflection
- In hindsight, I should have spent more time figuring out how to add a proper datetime library to Nuxt. Nuxt auto converting the YYYY-MM-DD dates in the lesson front matter burned soooo much time.
- Recap from last night: ended up working on Rick, where I didn't clone the code journal
- Added placeholder lessons so I could work on the schedule
- At some point, Nuxt broke and is giving the error:
TypeError: Unsupported field type for full text search
- It's very irritating that the location of the error isn't shown; just the stack trace from within the framework. Ugh.
- Goal: Since I didn't commit at any point, I have to copy the current files and gradually drag them over from scratch in order to narrow down the issue. I should have done a test build early to make sure my new placeholder files were working :/
- This is why I don't like branches: there's no way to copy files to a new branch without copying a branch to a new folder.
- Fixed! I was using
[description here]
as a placeholder in the front matter, which is reserved for arrays in YAML. Still sucks that the errors wouldn't tell me that. - I deleted the Dasa days during troubleshooting last night which I'll have to add back manually.
- BUT, first I'm going to commit :)
- Added Dasa days and committed. Moving on...
Goal: fetch all lesson days and merge into a single array.
- Plan: going to try
Promise.all()
to pull all lessons using code from existing Courses pages. - Done. It was fairly straight forward but the
.then
syntax was yucky so figured out how to do it withawait
; much nicer.
Goal: sort an array of objects by date
- Plan:
- figure out how Nuxt handles dates
- sort by date
- I read a little into setting up filters and decided to go native
Date
object. Sorting is a little magical but the syntax is pretty straight forward.
Goal: Divide a list of sorted days into weeks.
- First decision: do I do this in
script
ortemplate
?- Since I'm not familiar with Vue syntax, I'll do this in vanilla js and build a nested array of weeks so I can move complete weeks to a different container in the
template
.
- Since I'm not familiar with Vue syntax, I'll do this in vanilla js and build a nested array of weeks so I can move complete weeks to a different container in the
- Next decision: Do I go native
Date
again or try Luxon or something?- While it would be fun to figure out how to calculate week number programmatically, I'll need to install a date library eventually so I might as well try Luxon.
- Got a weird "fromMarkdown is not a function error" when running
npm run dev
which side tracked me.- switched to main branch and it still gave the error.
- deleting
package-lock.json
andnode_modules
with an install and audit finally fixed the issue (for now). Not sure how this could have broken?
- Not sure how to install luxon as a nuxt module? I've
npm install vue-luxon
but adding it to the Nuxtplugin
property in the config gives me a "plugin not found" error.- most likely have to add this on the vue level but need to learn more about how that works within Nuxt.
- Starting to feel the rage. This must be how the students must feel. Constant searching on Google is failing me "nuxt vue-luxon", and any variation on it, returns the same list of useless pages.
- Note for teaching: rage quitting is real. Right now I want to punch every Nuxt dev in the face for making shitty assumptions about me.
- Docs to the rescue! Unless this page sucks.
- Successfully installed
vue-luxon
(I think) but hitting a roadblock trying to access it from a component.-
vue-luxon
docs say usethis
:this.$luxon("2020-10-05T14:48:00.000Z")
But
this
is not defined. -
no variations I can think of are working :(
-
Goal: Install vue-luxon
locally, or I'll try installing vanilla luxon.
- After a break, and some research, I found this tutorial:
- Ugh, giving up on Luxon for now. Going to try doing the week-number math manually.
Goal: Auto prepend the lesson plan titles with the course code without having to add it to every markdown file.
- Does the nuxt content module support directory json/yaml files that contain default front matter variables for lessons?
- It doesn't look like it?
- Backup plan: build a superset yaml file that feeds the fetch loop for all the content that's date centric
- lessons
- holidays
- assignment due dates
- important milestones
- "last day to get 4 dailies in before end of course"
- didn't get very far.
Goal: Add lesson placeholders for building WBDV W22 Schedule.
- Plan: Start with all of Jan, plus Dasa Days and the first day of each course transition.
- forgot to commit last night. Starting back on the main branch and had to get rid of the changes.
- R+D:
git stash
- R+D:
- Repo
- Goal: Test
markdownit
install - where's the documentation?
- Nice! Ash linked to the documentation in
nuxt.config.js
. - Search:
remark vs markdown-it
- featured: Super nerdy critique in favour of remark
remark
looks pretty cool- damn, it doesn't look like there's a way to add classes?
- never mind! It's all about
remark-directive
(for now, until all the new plugins are ported to remark version whatever)
- Anyway, back onto testing definition lists.
- can't seem to get it to work. Going to try adding
remark-directive
to see if I can narrow this down. remark-directive
doesn't work either. I think it's time to give up for the night and ask Ash. Maybe a pair coding session?